Logique des prédicats, théorie des ensembles

Introduction

La logique des prédicats prolonge le raisonnement introduit en logique propositionnelle en permettant d’exprimer des propriétés paramétrées : les prédicats. Elle apparaît non seulement en mathématiques et en informatique, mais également en intelligence artificielle, en philosophie et en linguistique. À l'instar de la logique propositionnelle, c'est un langage doté de sa propre syntaxe, qui enrichit celui de la logique propositionnelle qui en devient un sous-langage, et la sémantique s’y greffe dans un second temps. La théorie ZF, quant à elle, fournit les objets sur lesquels ces propriétés peuvent opérer : les ensembles. Elle joue ainsi un rôle fondamental en informatique, où elle fournit les outils nécessaires pour représenter et raisonner rigoureusement sur des données structurées.

Dans cette perspective, la théorie ZF adjoint au langage prédicatif l'unique symbole non logique \(\in\), dont des axiomes régissent l'usage : c'est cette combinaison qui constitue la théorie des ensembles♯ La théorie des ensembles élaborée par Zermelo et Fraenkel présentée ici n'a rien de canonique, d'autres théories des ensembles sont possibles.. Cette théorie n'explique pas ce que sont les ensembles – des sacs de billes sont bien plus explicites pour cela – mais en propose un codage systématique.

Autrement dit, la logique des prédicats fournit les mécanismes généraux permettant d’énoncer et d’articuler des propriétés : les objets mathématiques informels y sont reconstruits sous forme de structures manipulables. Les axiomes de la théorie des ensembles jouent le rôle de règles de construction qui déterminent ce qu'il est permis de construire, en excluant notamment les constructions à l'origine des paradoxes classiques. Cette analogie avec les langages de programmation n’est pas seulement heuristique, elle éclaire le fait que ce cadre fournit un support formel dans lequel l’activité mathématique peut s’exprimer, se développer et se vérifier, en permettant d’écrire, de transformer et de contrôler des expressions symboliques selon des règles précises.

La médiathèque

Vous devez développer un moteur de recherche pour une médiathèque numérique. Un usager souhaite trouver tous les documents de la médiathèque qui parlent de robot(s) ou de chat(s), mais qui ne mentionnent pas l'intelligence artificielle. Le corpus* Ce corpus n'est pas réaliste. Il a été réduit ici à une poignée d'entrées afin de pouvoir être analysé à la main et de comprendre les mécanismes que nous mettrons en œuvre pour répondre à cette question. La réalité pour ce type de recherche serait plus proche de dizaines de milliers voire de millions de documents. de cette médiathèque est le suivant :

Avant même de concevoir un algorithme capable de répondre automatiquement à cette requête, et plus généralement à toute requête de ce type, une question se pose.

Question :

Comment traduire avec précision la requête de l’usager, de manière à pouvoir automatiser la recherche des documents qui la satisfont ?

Nous y reviendrons à la fin du chapitre en proposant une formalisation rigoureuse et complète de ce problème une fois étudiés les nouveaux concepts introduits : prédicats et ensembles.

Théorie mathématique

Axiomes et démonstrations

Une théorie ma­thé­ma­ti­que est un ensemble d'affirmations, les assertions ou propositions vraies. Une assertion peut être admise, auquel cas on parle d'axiome ou de postulat – c'est in­con­tour­na­ble, on ne peut pas créer une théorie ex nihilo, – ou être obtenue à partir d'assertions préétablies, dont les axiomes, et d'un ensemble de règles de déduction logique (comme le modus ponens par exemple).

À gauche, un tas de pièces lego dépareillées ;
                à droite, les mêmes pièces assemblées pour former le mot MATHS.

Une fois fixés les axiomes et les règles déductives, une théorie mathématique est parfaitement déterminée, faire des mathématiques ne consiste qu'à explorer l'arbre des déductions possibles dans cette théorie si l'on caricature la discipline en un simple jeu formel d'assemblage, comme un jeu lego ® ou une partie d'échecs. Cependant, la pratique humaine ne se limite pas à explorer mécaniquement tous les assemblages/coups possibles, elle fait appel à l'intuition, à la créativité et à la stratégie. La communauté mathématique ne se contente pas d'appliquer des règles, elle invente de nouvelles méthodes, formule des conjectures et choisit des pistes prometteuses dans l'arbre des possibles. Mais plus fondamentalement encore, elle n'est pas confinée dans un champ clôturé par un système fixé une fois pour toutes – comme la théorie ZF introduite ici –, elle s'interroge également sur ses propres structures logiques et la nature de ses fondements.

La logique des prédicats enrichit la logique pro­po­si­tion­nel­le en fournissant de nouveaux mécanismes – variables, prédicats, quantificateurs – pour construire des énoncés plus expressifs. Ce pouvoir d'expression n'est pas circonscrit à un cadre purement syntaxique : il permet d'appréhender plus fidèlement le monde qui nous entoure, chaque fois qu'il s'agit de décrire des objets, leurs propriétés et les relations qui les lient. Ce langage n'entre donc pas en concurrence avec celui de la logique propositionnelle, il l'englobe. Une théorie particulière, comme celle des ensembles que nous étudierons plus loin, viendra compléter ce langage logique de ses propres symboles.

Cette approche formelle, voire kafkaïenne, des mathématiques ne doit pas faire perdre de vue qu'elles seraient im­pra­ti­ca­bles ou pour le moins considérablement entravées si l'on s'in­ter­di­sait l'usage de la langue naturelle pour s'exprimer. Répétons-le, faire des mathématiques ne peut pas se résumer à la construction d'énoncés formels qui respectent une syntaxe stricte, à la manière d'un langage de programmation. Parler d'un entier naturel \(n\) pair n'est pas moins rigoureux que d'écrire, pour un entier \(n\) fixé :

\begin{equation} \label{eq:entierpair} n\in\N\ \text{et la proposition}\ \exists k\ (k\in\N) \land (n={\color{#FF8}2}k)\ \text{est vraie.} \end{equation}

La proposition \(\exists k\ (k\in\N) \land (n=2k)\) est en revanche bien plus efficace que sa version en langue naturelle☆Cette proposition mobilise des ingrédients que le lecteur a certainement déjà croisés dans d'autres cours, sans nécessairement savoir à quelle strate du langage chacun appartenait : un prédicat, une quantification, et le symbole \(\in\) qui, on le verra, n'appartient pas à la logique elle-même mais au langage particulier de la théorie des ensembles. C'est un avant-goût typique de l'articulation entre prédicats et ensembles que ce chapitre se propose de rendre moins nébuleux. s'il faut démontrer que le carré d'un entier pair est pair : en supposant \(n\) pair, d'après \((\ref{eq:entierpair})\), on dispose d'un entier naturel \(k\) tel que \(n=2k\), et on démontre successivement que les trois implications suivantes sont vraies grâce aux propriétés des opérations arithmétiques :

\begin{align*} \boxed{n={\color{#FF8}2}k}\ &\then\ n^2=({\color{#FF8}2}k)^2 \quad&&\text{( on élève au carré )}\\ n^2=({\color{#FF8}2}k)^2\ &\then\ n^2=4k^2\quad&&( \text{car}\ (ab)^2=a^2b^2 )\\ n^2=4k^2\ &\then\ \boxed{n^2={\color{#FF8}2}(2k^2)}\quad&&\text{( on met \(2\) en facteur )} \end{align*}

Et la transitivité de l'implication nous donne

\begin{equation} \label{eq:endproof} \boxed{n={\color{#FF8}2}k}\ \then\ \boxed{n^2={\color{#FF8}2}({\color{#48F}2k^2})} \end{equation}

L'égalité \(n=2k\) étant vraie par choix de \(k\), la règle du modus ponens appliquée à l'implication \((\ref{eq:endproof})\) nous donne \(n^2=2{\color{#48F}K}\) avec \({\color{#48F}K}:={\color{#48F}2k^2}\in\N\) : la proposition \(\exists K\ (K\in\N)\land(n^2=2K)\) est vraie, autrement dit \(n^2\) est pair. Et comme l'entier pair \(n\) a été choisi quelconque, le résultat vaut pour tout entier pair : le carré d'un entier pair est pair.

Notons que sur le terrain du langage, les ma­thé­ma­ti­ques et l'informatique font en quelque sorte chemin inverse. La nécessité d'un cadre rigoureux pour raisonner a contraint les mathématiciens à s'éloigner de la langue naturelle en développant un langage de plus en plus formel et astreignant, alors que les informaticiens cherchent au contraire à développer des langages de programmation de plus en plus proches de la langue naturelle. Un langage de pro­gram­ma­tion est en quelque sorte un langage ma­thé­ma­ti­que idéalisé, ne serait-ce que du point de vue lexical et syntaxique, les codeurs en font la douloureuse expérience au quo­ti­dien, la moindre erreur de syntaxe est im­mé­dia­te­ment sanc­tion­née.

On rappelle la définition introduite au chapitre précédent :

Une séquence de déductions logiques permettant d'établir de nouvelles as­ser­tions à partir d'as­ser­tions déjà acquises – initialement les axiomes –, s'appelle une dé­mons­tra­tion ou une preu­ve.

Une nouvelle assertion obtenue par déduction est appelée théorème, ou lemme si le résultat est une étape importante pour l'obtention d'un théorème, ou parfois pro­po­si­tion­ (au sens informel donc), ou encore corollaire lorsqu'il s'agit d'une con­sé­quen­ce directe d'un théorème. Stricto sensu, chaque proposition intermédiaire obtenue dans une démonstration constitue un théorème, mais nous ne mettons en évidence que celles qui nous pa­rais­sent importantes, les autres restent dans l'anonymat.

Explication ou preuve ?

Le rôle premier d'une démonstration est de valider une proposition. Elle agit comme un processus de certification qui n'explique pas nécessairement pourquoi elle est vraie, mais comment. En général, on débute par la compréhension du résultat, même parcellaire, puis on tente de le valider formellement, rarement l'inverse. Parfois l'explication est transposable en preuve, en particulier quand il s'agit d'un processus constructif.

Ce processus formel de certification d'un résultat peut être particulièrement abscons. Il est donc essentiel de trouver des arguments, même informels, pour comprendre pourquoi une proposition est vraie. C'est ce qui fait polémique (au dernier trimestre 2026) entre le travail des mathématiciens sur les preuves et celui des llm auxquels on demande d'inférer des certificats comestibles pour des assistants de preuve… De la même manière, un algorithme s'adresse à un être humain et explicite comment obtenir un résultat, alors que le code exécutable qui le réalise n'est plus qu'une suc­ces­sion d'instructions parfaitement obscures. Le lecteur pourra s'en convaincre en lisant celui de n'importe quel programme une fois compilé.

Illustrons ça avec le célèbre théorème de Pythagore qui admet une explication parfaitement convaincante :

A B C a b a b b a a b h h 2 a a b b a b a b a 2 b 2 h h
Version géométrique du théorème de Pythagore.

Les deux grands carrés à gauche et à droite dans la figure ci-dessus ont des côtés de même longueur \(a+b\). On recompose le premier carré en déplaçant les \(4\) triangles rouges qu'il contient de manière à former les deux rectangles de côtés de mesure \(a\) et \(b\) qui apparaissent dans le second carré. On en déduit que les aires bleues à gauche et à droite sont égales :

Le carré de l'hypoténuse \(\color{#08F}h\) d'un triangle rec­tang­le est égal à la somme des carrés des longueurs des autres côtés \(\color{#08F}a\) et \(\color{#08F}b\) : \[{\color{#08F}h^2}={\color{#08F}a^2+b^2}.\]
On rappelle que si \(u\) et \(v\) sont deux vecteurs du plan, alors \[u\cdot v=\Vert u\Vert\,\Vert v\Vert\,\cos(\widehat{u,v})\] où \(u\cdot v\) désigne le produit scalaire des vecteurs \(u\) et de \(v\). On en déduit que \(u\cdot u=\Vert u\Vert^2\) puisque \(\cos(\widehat{u,u})=1\).

On considère un triangle \(ABC\) rectangle en \(A\) de côtés \([AB]\), \([AC]\) et d'hypoténuse \([BC]\). On calcule alors \begin{align*} BC^2&=\Vert\,\overrightarrow{BC}\,\Vert^2\\ &=\Vert\,\overrightarrow{BA} + \overrightarrow{AC}\,\Vert^2\quad(\text{Chasles})\\ &=\Vert\,\overrightarrow{AC}-\overrightarrow{AB}\,\Vert^2\\ &=(\overrightarrow{AC}-\overrightarrow{AB})\cdot(\overrightarrow{AC}-\overrightarrow{AB})\\ &=\overrightarrow{AC}\cdot\overrightarrow{AC}-2\,\overrightarrow{AB}\cdot \overrightarrow{AC}+\overrightarrow{AB}\cdot\overrightarrow{AB}\quad(\text{Bilinéarité du produit scalaire \(\cdot\)})\\ &=\Vert\,\overrightarrow{AC}\,\Vert^2-2\,\overrightarrow{AB}\cdot\overrightarrow{AC}+\Vert\,\overrightarrow{AB}\,\Vert^2 \\ &=\Vert\,\overrightarrow{AC}\,\Vert^2+\Vert\,\overrightarrow{AB}\,\Vert^2 -2\,\Vert\,\overrightarrow{AB}\,\Vert\,\,\Vert\,\overrightarrow{AC} \,\Vert\,\,\underbrace{\cos(\widehat{\overrightarrow{AB},\overrightarrow{AC}})}_{0} \end{align*} Et finalement \(BC^2=AC^2+AB^2\) car \(\overrightarrow{AB}\perp\overrightarrow{AC}\).

La dé­mons­tra­tion géométrique dans la figure ci-dessus est informelle mais justifie de manière compréhensible le résultat. Une preuve formelle utiliserait, par exemple, les outils de la géométrie cartésienne comme les vecteurs et le produit scalaire pour établir le résultat de manière algébrique (déplier la preuve sous le théorème).

Nous avons déjà mentionné trois méthodes communes qui sont utilisées pour faire une dé­mons­tra­tion :

  1. Par modus ponens. Si \(P\) et \(Q\) sont deux propositions telles que \(P\) est vraie et \(P\Rightarrow Q\) est vraie, on en déduit que la proposition \(Q\) est vraie ;
  2. Par modus tollens (contraposition). Si \(P\) et \(Q\) sont deux propositions telles que \(P\Rightarrow Q\) est vraie et que \(\neg Q\) est vraie, on en déduit que la proposition \(\neg P\) est vraie ;
  3. Par l'absurde. Pour démontrer qu'une proposition \(P\) est vraie, on suppose que la proposition \(\neg P\) est vraie, i.e. \(\neg P\) est un nouvel axiome de la théorie, puis on cherche une proposition \(Q\) telle que la proposition \(Q\land \neg Q\) est vraie, prouvant ainsi que cette théorie est contradictoire d'après le tiers exclu ce qui invalide la nouvelle théorie et disqualifie cet axiome.

Nous verrons plus loin dans ce chapitre, puis au chapitre Combinatoire, deux autres méthodes de dé­mons­tra­tion :

  1. Par disjonction de cas.
  2. Par ré­cur­ren­ce.

Logique des prédicats

Un canevas pour des langages

Le mot prédicat n'est pas une invention de logiciens : c'est, depuis 2016, un terme officiel du programme scolaire français, enseigné dès le CM1 : une phrase s'y décompose en un sujet – ce dont on parle – et un prédicat – ce que l'on en dit *Le prédicat grammatical se compose le plus souvent d'un verbe et de ses compléments..

Ce que la logique en retient est très proche, à un détail près : en grammaire, le sujet et le complément sont fixés, si bien qu'une phrase complète est d'emblée vraie ou fausse, c'est donc une proposition au sens de la logique propositionnelle†Manifestement les grammairiens communiquent peu avec les logiciens.. En logique des prédicats, on va au contraire dépouiller l'articulation elle-même de tous les termes qu'elle relie : le prédicat n'est plus que la relation nue et chacun des termes qu'elle relie, sujet comme complément, reste à l'extérieur, comme autant de places vides. Par exemple :

Quel que soit le nombre de places laissées ouvertes, tant qu'elles ne sont pas toutes remplies, on ne peut pas attribuer une valeur de vérité à ces phrases : c'est précisément ce mécanisme – une relation dépouillée des termes qu'elle articule, qui ne devient une proposition qu'une fois tous ces termes fournis – que la logique des prédicats va formaliser.

Comme pour la logique propositionnelle, il faut se donner un lexique de symboles avant de pouvoir composer des prédicats. On hérite sans changement des constantes \(\top\) et \(\bot\), des connecteurs logiques \(\neg,\land,\lor,\Rightarrow,\Leftrightarrow,\ldots\) et des parenthèses. Les variables propositionnelles, en revanche, ne sont pas reconduites telles quelles : on verra plus loin qu'elles reviennent sous la forme d'un cas particulier d'une nouvelle catégorie de symboles. À ce lexique s'ajoutent donc quatre nouvelles catégories :

  1. Des variables individuelles : des symboles désignant un individu quelconque – un objet –, à ne pas confondre avec une variable propositionnelle, qui désigne directement une proposition. On les prend généralement dans les dernières lettres de l'alphabet latin, \(x\), \(y\), \(z\ldots\)
  2. Des symboles prédicatifs : des symboles arbitraires, généralement pris dans les premières lettres de l'alphabet latin en majuscule, \(P\), \(Q\), \(R\ldots\), chacun muni d'une arité fixée.
  3. Le symbole d'égalité \(=\).
  4. Les quantificateurs \(\forall\) et \(\exists\), dont on précisera le sens plus loin.

Ces conventions typographiques – dernières lettres de l'alphabet pour les variables, majuscules pour les symboles prédicatifs – ne sont que des usages, pas des règles : rien n'interdit par exemple de noter un prédicat \(p(x,y)\), quitte à réutiliser une lettre déjà rencontrée comme variable pro­po­si­tion­nelle dans un chapitre précédent. On dispose d'une réserve inépuisable de variables individuelles \(x_0,x_1,x_2,\ldots\), à la manière de la bourse de Fortunatus §Héros d'un conte populaire allemand, Fortunatus reçoit de la Fortune une bourse inépuisable : on y puise autant qu'on veut, elle ne se vide jamais. : chaque prédicat n'en utilise qu'un nombre fini, mais on peut toujours en prendre une nouvelle. Les symboles prédicatifs, eux, peuvent être en nombre fini : la théorie ZF n'en utilisera qu'un seul.

Ce lexique, comme celui de la logique propositionnelle, ne dépend d'aucune théorie : aucun de ces symboles ne présuppose un domaine particulier d'objets ni une théorie mathématique donnée. C'est précisément ce qui permettra, plus loin, à une théorie particulière comme la théorie ZF, de l'enrichir de son propre vo­ca­bu­lai­re.

Nous sommes à présent en mesure de donner une définition formelle d'un prédicat, à partir du lexique qu'on vient de fixer. La notion d'arité nous est déjà familière : de même qu'un con­nec­teur \(q\)-aire relie \(q\) propositions, un symbole prédicatif d'arité \(q\) est relié à \(q\) variables individuelles entre parenthèses, généralement notées de manière préfixe : \(P(x,y)\) pour un symbole \(P\) d'arité \(2\), \(R(x,y,z)\) pour un symbole \(R\) d'arité \(3\), et ainsi de suite – on parle alors de prédicat \(q\)-aire.

Un prédicat, ou formule prédicative, est défini inductivement par les règles suivantes :
  1. Si \(s\) et \(t\) sont des variables individuelles, \((s=t)\) est un prédicat.
  2. Si \(P\) est un symbole prédicatif d'arité \(q\) et \(x_1,\ldots,x_q\) des variables individuelles, \(P(x_1,\ldots,x_q)\) est un prédicat.
  3. Si \(\varphi\) est un prédicat, \(\neg\varphi\) est un prédicat.
  4. Si \(\varphi\) et \(\psi\) sont des prédicats et \(\diamond\) un connecteur binaire, \((\varphi\diamond\psi)\) est un prédicat.
  5. Si \(\varphi\) est un prédicat et \(x\) une variable individuelle, \(\forall x\,\varphi\) et \(\exists x\,\varphi\) sont des prédicats.
Tout prédicat obtenu par les règles \(1\) ou \(2\) est dit atomique. Aucune autre expression n'est un prédicat.
Informellement, un prédicat est un énoncé contenant une ou plusieurs variables, tel qu'en fixant une valeur à chacune d'elles on obtient une proposition – c'est précisément ce que vérifient, un nombre fini de fois, les cinq règles ci-dessus. On notera en particulier que rien n'interdit à l'arité \(q\) d'un symbole prédicatif d'être nulle : un symbole prédicatif d'arité \(0\) n'est jamais qu'une variable propositionnelle. Le calcul propositionnel se trouve ainsi entièrement encapsulé dans le calcul des prédicats : toute proposition en est un cas particulier, celui où il n'y a plus aucune variable à instancier.

La règle \(5\) fournit une seconde façon d'atteindre ce même cas limite : si \(\varphi\) n'a pas d'autre variable libre que \(x\), alors \(\forall x\,\varphi\) (ou \(\exists x\,\varphi\)) n'a plus aucune variable restant à fixer, et devient à son tour une proposition – quand bien même \(\varphi\), lui, ne l'était pas encore. Si \(\varphi\) a d'autres variables libres que \(x\), en revanche, celles-ci demeurent, et \(\forall x\,\varphi\) reste un authentique prédicat ; les notions de variable libre et liée, précisées un peu plus loin, permettront de le dire avec exactitude.

Cette définition ne met en jeu aucun symbole propre à une théorie particulière – ni \(\in\), ni aucun autre. Les seuls symboles non logiques y sont les symboles prédicatifs \(P,Q,R,\ldots\), dont on ne précise ni le nombre ni le sens. Le choix de ces symboles, chacun avec son arité, s'appelle une signature : c'est la case vide du lexique. Chaque signature produit son propre langage, construit selon les mêmes cinq règles. La théorie des ensembles choisira la plus réduite qui soit, un unique symbole binaire : \(\in\).

L'égalité a, parmi les symboles prédicatifs, un statut particulier : contrairement à \(P,Q,R,\ldots\), dont le sens reste à la charge de chaque théorie particulière, elle a une interprétation fixée une fois pour toutes, commune à toute théorie du premier ordre : la proposition \(x\) est égal à \(y\), codée \begin{equation} x=y \end{equation} exprime que les expressions \(x\) et \(y\) désignent le même objet.

Si \(x\) et \(y\) satisfont \(x=y\), cela entraîne qu'ils sont synonymes, ou, pour reprendre un vocabulaire familier à l'informaticien, des alias l'un de l'autre : deux étiquettes différentes désignant le même objet. On peut donc les substituer dans n'importe quelle expression ma­thé­ma­ti­que sans modifier son interprétation logique.

En substance, \(=\) est un symbole prédicatif comme les autres – d'arité \(2\) (binaire), il faudrait donc utiliser la même notation préfixe \(=(s,t)\) fixée par la règle \(2\) : \(P(x_1,x_2,\ldots,x_q)\). Ce choix est purement typographique : il ne modifie en rien la définition inductive elle-même. De nombreux symboles prédicatifs binaires suivront ce même choix d'écriture dans la suite. Ce qui le distingue de \(P\), \(Q\), \(R\ldots\), ce n'est donc pas sa forme, mais son statut : ces derniers restent anonymes, muets de sens, en attente d'être interprétés par une théorie particulière, alors que \(=\) est désanonymisé d'emblée – son interprétation est fixée une fois pour toutes, universelle, la même dans toute théorie du premier ordre. C'est ce statut, pas son arité, qui justifie qu'on lui consacre une règle à part (la règle \(1\)) plutôt que de le laisser comme une simple instanciation de la règle \(2\).

Les quantificateurs universels et existentiels

Précisons à présent le sens des deux quantificateurs annoncés dans notre lexique, qui permettent de construire des propositions à l'aide d'un prédicat \(P(x)\) et des règles syntaxiques pour les composer :

  1. Le quantificateur universel \(\forall\), qui se lit quel que soit ou pour tout, et s'utilise dans l'ex­pres­sion \begin{equation} \label{eq:universel0} \forall x\ {\color{#08F}P(x)} \end{equation} qui code la proposition Pour tout \(x\), la proposition \(P(x)\) est vraie.
  2. Le quan­ti­fi­ca­teur existentiel \(\exists\) qui se lit il existe, et s'utilise dans l'expression \begin{equation} \label{eq:existentiel0} \exists x\ {\color{#F80}P(x)} \end{equation} qui code la proposition Il existe \(x\) tel que la proposition \(P(x)\) est vraie. Notons qu'un tel élément n'est pas nécessairement unique.

Quand un quan­ti­fi­ca­teur précède une variable \(x\), on dit qu'elle est quantifiée ou qu'il s'agit d'une variable liée (sous-entendu à un quantificateur). On dit également va­ria­ble muette ou anonyme : elle peut être remplacée partout dans l'expression par n'im­por­te quelle autre variable qui n'y est pas présente sans en chan­ger le sens. On peut s'en convaincre en remplaçant \(x\) par \(y\) dans les deux expressions \((\ref{eq:universel0})\) et \((\ref{eq:existentiel0})\) : ces deux expressions sont donc bien des propositions et non des prédicats. Quand une variable n'est pas quantifiée elle est dite libre. Quand toutes les variables d'une formule de la logique des prédicats sont quantifiées, la formule est dite close.

On considère les expressions suivantes, où \(P\), \(Q\) sont des symboles prédicatifs binaires et \(R\) un symbole prédicatif unaire :
  1. \(P(x,y)\)
  2. \((x=y) \)
  3. \(\neg R(x) \)
  4. \((P(x,y)\land R(z)) \)
  5. \(\forall x\ Q(x,y) \)
  6. \(P(x\)
Pour chacune, indiquez si c'est un prédicat au sens de la définition formelle. Si oui, précisez la (ou les) règle(s) qui permettent de le construire, dans l'ordre. Si non, expliquez ce qui empêche sa construction.
  1. \(P(x,y)\) — prédicat, règle \(2\) (\(P\) d'arité \(2\), deux variables individuelles).
  2. \((x=y)\) — prédicat, règle \(1\).
  3. \(\neg R(x)\) — prédicat : \(R(x)\) par la règle \(2\) (\(R\) d'arité \(1\)), puis \(\neg R(x)\) par la règle \(3\).
  4. \((P(x,y)\land R(z))\) — prédicat : \(P(x,y)\) et \(R(z)\) par la règle \(2\), combinés par la règle \(4\) via le connecteur \(\land\), hérité de la logique propositionnelle.
  5. \(\forall x\ Q(x,y)\) — prédicat : \(Q(x,y)\) par la règle \(2\) (\(Q\) d'arité \(2\)), puis \(\forall x\,Q(x,y)\) par la règle \(5\). La variable \(y\) reste libre.
  6. \(P(x\) — n'est pas un prédicat, pour deux raisons indépendantes : la parenthèse n'est pas fermée, et même en l'ignorant, un seul argument est fourni à \(P\) alors que son arité est \(2\) — la règle \(2\) exige exactement \(q\) variables individuelles pour un symbole d'arité \(q\).
On considère les quatre prédicats suivants, où \(P\) est un symbole prédicatif binaire :
  1. \(P(x,y) \)
  2. \(\forall x\ P(x,y) \)
  3. \(\exists y\ P(x,y) \)
  4. \(\forall x\ \exists y\ P(x,y)\)
Pour chacun, précisez ses variables libres et ses variables liées.
Lesquels de ces quatre prédicats sont en réalité des propositions ?
  1. \(P(x,y)\) : \(x\) et \(y\) libres, aucune variable liée.
  2. \(\forall x\ P(x,y)\) : \(x\) liée, \(y\) libre.
  3. \(\exists y\ P(x,y)\) : \(y\) liée, \(x\) libre.
  4. \(\forall x\ \exists y\ P(x,y)\) : \(x\) et \(y\) toutes deux liées, aucune variable libre.
Seul le quatrième, \(\forall x\ \exists y\ P(x,y)\), est une proposition : c'est le seul dont toutes les variables sont quantifiées, donc le seul qui soit une formule close.
Que devient la règle \(2\) de la définition formelle lorsque l'arité \(q\) du symbole prédicatif \(P\) est nulle ? Comparez le résultat à la définition d'une variable propositionnelle donnée au chapitre précédent.
Avec \(q=0\), la règle \(2\) s'écrit : si \(P\) est un symbole prédicatif d'arité \(0\), alors \(P\) est un prédicat — sans parenthèses ni variables, puisqu'il n'y en a aucune à fournir. \(P\) devient donc un symbole atomique isolé, strictement de la même nature qu'une variable propositionnelle dans la définition du chapitre précédent : un symbole sans structure interne, admis directement comme formule par la clause de base. C'est très exactement ce que dit la remarque : un symbole prédicatif d'arité \(0\) n'est jamais qu'une variable propositionnelle sous un autre nom.
On considère les expressions suivantes, où \(P\) est un symbole prédicatif binaire :
  1. \((a=b) \)
  2. \(P(a,b) \)
  3. \((x=x) \)
  4. \(P(x,x)\)
Quelle règle de la définition formelle justifie chacune de ces expressions ? Rien n'empêcherait, syntaxiquement, de considérer \(=\) comme un symbole prédicatif ordinaire d'arité \(2\) et de fusionner les règles \(1\) et \(2\) en une seule. Pourquoi ne le fait-on pas ?
  1. \((a=b)\) — règle \(1\).
  2. \(P(a,b)\) — règle \(2\).
  3. \((x=x)\) — règle \(1\) : rien n'interdit que \(s\) et \(t\) coïncident.
  4. \(P(x,x)\) — règle \(2\), même remarque : rien n'interdit de répéter une variable dans plusieurs positions d'argument.
Syntaxiquement, rien n'empêcherait en effet de fusionner les deux règles : \(=\) pourrait très bien être traité comme un symbole prédicatif binaire ordinaire, et \((s=t)\) ne serait alors qu'une instance de la règle \(2\) parmi d'autres. Si on ne le fait pas, c'est pour une raison qui n'est pas syntaxique mais statutaire : contrairement à \(P\), \(Q\), \(R\ldots\), dont le sens reste à la charge de la théorie qui les adoptera, \(=\) a une interprétation fixée une fois pour toutes, la même dans toute théorie du premier ordre. Garder la règle \(1\) séparée, c'est inscrire cette différence de statut directement dans la grammaire : la présence même d'une règle à part signale, avant toute sémantique, que \(=\) appartient au noyau logique, alors que \(P,Q,R\) restent des emplacements vides qu'une théorie viendra remplir.

Théorie ZF

La théorie des ensembles de Cantor

La théorie ma­thé­ma­ti­que dans laquelle nous discourons, tout au moins dans ce cours, est une axiomatisation de la théorie des ensembles. Cette théorie a été développée par G. Cantor*Mathématicien allemand de la fin du 19ème siècle. à la fin du 19ème siècle, puis axiomatisée par les mathématiciens allemands E. Zermelo et A. Fraenkel pour en éliminer les paradoxes. Elle est l'aboutissement de ques­tion­ne­ments philosophiques sur la nature du rai­son­ne­ment et de la construction des ensembles qui ont culminé à la charnière du xix-ème et du xx-ème siècle. Bien entendu, les mathématiciens n'ont pas attendu le xx-ème siècle et cette théorie pour faire des démonstrations. L'apparition de con­tra­dic­tions et de paradoxes, conséquence de manipulations sans contraintes des ensembles infinis, a mis en péril l'édifice mathématique et a nécessité d'en fixer les règles. Pour faire une métaphore routière, conduire sur les routes sans fixer quelques règles de circulation peut générer des accidents.

Cette théorie identifie tous les objets manipulés à des ensembles, nombres, fonctions, relations, vecteurs, etc. Elle fournit un nombre limité d'axiomes et de règles pour justifier leur existence ou pour les construire. Elle n'est pas la théorie des ensembles, au sens défini singulier, bien que nous employions souvent cette expression, mais plutôt un codage (au sens informatique du terme) particulier et cohérent des objets qui étaient déjà utilisés en ma­thé­ma­ti­ques. La plupart des axiomes expriment des propriétés qui semblent évidentes pour les ensembles tels que nous les concevons naïvement. Ils précisent dans quel cadre nous pouvons construire de nouveaux ensembles à partir de ceux que nous connaissons déjà.

La raison de cette théorie n'est pas d'expliquer ce qu'est un ensemble, mais d'établir des règles de cons­truc­tion afin d'éviter des paradoxes. Nous ne ferons qu'effleurer ces questions délicates dans ce cours de li­cen­ce, elles seront à nouveau abordées dans un cours de calculabilité de mas­ter d'in­for­ma­ti­que. Dans la suite nous ne présenterons que les axiomes que nous utilisons in­ten­si­ve­ment, ils il­lus­trent la démarche qui sous-tend cette théorie et dont la dimension systématique est proche de la théorie des langages en informatique.

Plus prosaïquement, nous concevons un en­sem­ble comme une collection d'objets, comme un re­grou­pe­ment, à la manière d'un sac de billes. Cette vision informelle est non seulement légitime mais in­dis­pen­sa­ble pour élaborer nos rai­son­ne­ments, il est donc exclu de la sacrifier sur l'autel du formalisme, elle est suffisante pour la licence. C'est celle de Georg Cantor :

On appelle en­sem­ble toute collection \(X\) d'objets définis et discernables. Un tel objet est appelé élément ou membre de \(X\) et on dit que l'objet appartient à \(X\) ou encore que \(X\) contient cet objet.

Les deux mots clés dans cette définition sont les mots définis et discernables. Le premier signifie que l'on doit être en mesure de dire pour tout objet s'il est un élément ou non de l'ensemble \(X\). Le second signifie que l'on doit être en mesure de distinguer les éléments d'un ensemble. Ces deux conditions expriment qu'un ensemble est entièrement caractérisé par les éléments qu'il contient.

La condition définis fait émerger un symbole propre au langage de la théorie des ensembles : la relation d'appartenance \(\in\). La proposition \(x\) est un élément de \(X\) est codée par l'expression \begin{equation} x\in X. \end{equation} Quant à la condition discernables, elle s'appuie sur l'égalité \(=\), dont on a déjà vu qu'il s'agit d'un symbole logique, indépendant de toute théorie particulière.

Rien n'empêche un ensemble d'être lui-même l'élément d'un autre ensemble.

D'autres notations sont spécifiques à la théorie des ensembles, en particulier l'accolade ouv­ran­te { et l'accolade fermante }. Quand le nombre d'éléments qui caractérisent un ensemble \(X\) est fini – la définition formelle de la finitude dans le cadre de cette théorie sera définie plus tard –, on peut représenter cet ensemble par la liste de ses éléments délimitée par ces deux sym­boles respectivement. Par exemple : \begin{align} \label{eq:ens4} X=\{1,f,3,x\}. \end{align} dont les éléments sont : \(1\), \(f\), \(3\) et \(x\). Cette écriture de l'ensemble \(X\) est dite en extension.

Les deux symboles \(\{\) et \(\}\) sont chargés de sens, faire l'accolade est sy­no­ny­me d'embrasser et ceci désigne l'action qui consiste à entourer quelque chose ou quelqu'un avec ses bras, ce que représentent explicitement ces symboles.
Comme un ensemble est entièrement déterminé par ses éléments, les répétitions éventuelles d'un même objet dans l'écriture en extension d'un ensemble sont redondantes, ainsi \[\{a,a,b,a,c,b\}=\{a,b,c\}.\] La raison est simple : la théorie impose que les éléments d'un ensemble soient discernables, un même identificateur – \(a\) dans notre exemple – ne peut donc jouer plusieurs rôles à la fois. La tension que peut ressentir le lecteur à ce sujet est compréhensible, nous envisageons naïvement un ensemble de manière matérielle, comme un sac dans lequel on pourrait ranger plusieurs exemplaires d'un même objet, comme trois stylos bleus par exemple. Cependant, le fait de ne pouvoir les distinguer visuellement ne les rend pas pour autant égaux, au même titre que les triplets d'une fratrie peuvent être confondus mais sont bien des individus différents.

D'autre part, l'ordre dans lequel apparaissent les éléments d'un ensemble n'a aucune importance, par exemple : \[\{a,b,c\}=\{b,a,c\}\ \text{et}\ \{a,b,c\}=\{a,c,b\},\ \text{etc.}\]

Nous utiliserons deux notations pour l'égalité, le symbole simple \(=\) et le symbole composé \(:=\). Ils désignent la même relation d'égalité : les deux points qui précèdent l'égalité ont un simple rôle sémantique dans le métalangage mathématique. Ils signalent au lecteur que le terme à gauche est défini par celui de droite, généralement au moyen d'une construction mathématique. L'égalité qui en découle est alors une conséquence de cette définition. Ainsi, on distinguera l'assertion \(3=1+2\) de la définition \(X:=\{a,b,c\}\). Cette dernière signifie que \(X\) est l'ensemble constitué des trois objets \(a\), \(b\) et \(c\), et permet alors de former la nouvelle assertion \(X=\{a,b,c\}\). Cette notation est particulièrement commode et a également été popularisée en informatique par des langages comme le Pascal, qui utilisent \(:=\) pour distinguer l'affectation de l'égalité.

Prédicats et ensembles

Une formule du calcul des prédicats, comme \(\forall x\ \exists y\ P(x,y)\), n'est jusqu'ici qu'un gabarit : de la syntaxe pure, doublement vide de sens. Elle comporte d'une part des symboles prédicatifs \(P,Q,R\ldots\) anonymes, dont on ignore quelle relation ils désignent, et d'autre part des places – ses variables – dont on ignore quels objets viendront les occuper. Dans les exemples du début de la section précédente, le prédicat (a réalisé) était fixé et seules les places étaient vides ; ici, même le prédicat est anonyme. La théorie ZF comble le premier vide : elle substitue aux symboles anonymes son unique symbole \(\in\), et le gabarit \(\forall x\ \exists y\ P(x,y)\) devient la formule \(\forall x\ \exists y\ x\in y\), qui parle désormais d'appartenance. Les places, elles, restent ouvertes : ce sont des ensembles qui viendront les occuper.

Le prédicat \(x\in\{1,2\}\), par exemple, ressemble à une instance de la règle \(2\) : le symbole \(\in\), en notation infixe, appliqué à \(x\) et à \(\{1,2\}\). Ce n'en est pas tout à fait une, car \(\{1,2\}\) n'est pas une variable mais une abréviation. Il en va de même de \(\varnothing\), \(1\), \(2\), \(\subseteq\), \(\cup\), \(\leqslant\) et de la plupart des écritures mathématiques usuelles : chacune pourrait en principe être dépliée en une formule n'utilisant que \(\in\) et \(=\), comme un programme se compile en code machine. Le résultat serait parfaitement illisible et nous ne le ferons jamais : il suffit de savoir que c'est possible.

(1) L'expression \(\neg(x\in y)\) est un prédicat à deux variables \(x\) et \(y\). Ainsi l'expression \((x\in\{1,2\})\land(\neg(x\in y))\) est un nouveau prédicat à deux variables \(x\) et \(y\).

(2) On peut également combiner des prédicats et des propositions, comme \((1=2)\then (x\in y)\), qui définit ici un prédicat à deux variables \(x\) et \(y\).

On remplace souvent l'expression \(\neg (x\in X)\) par l'expression \(x\not\in X\) et l'expression \(\neg(x=y)\) par \(x\neq y\).

On conserve la même terminologie que pour la logique propositionnelle quand on fixe la valeur d'une ou plusieurs variables d'un prédicat, il s'agit encore d'une interprétation. Notons que si une seule variable a été interprétée dans un prédicat à \(q\) variables, la nouvelle expression est un prédicat à \(q-1\) variables.

(1) L'expression \(x\in\{1,2\}\) est un prédicat \(P(x)\) à une variable \(x\) et \(P(4)\) est une proposition qui est interprétée comme fausse.

(2) En anticipant l'étude de l'arithmétique, l'expression \(n\leqslant 2k\) est un prédicat \(P(n,k)\) à deux variables \(n\) et \(k\) entières, \(P(n,2)\) est le prédicat \(n\leqslant 4\) à une variable \(n\) et \(P(1,2)\) est une proposition interprétée comme vraie, alors que \(P(3,1)\) est une proposition interprétée comme fausse.

On considère les quatre expressions suivantes : \[ 2+3=5,\qquad x+1=0,\qquad x+y=0,\qquad x=k+2. \]
Indiquez lesquelles sont des propositions et lesquelles sont des prédicats. Lorsqu'il s'agit d'un prédicat, précisez combien il contient de variables libres.

Dans l'expression \(x=k+2\), on suppose d'abord que \(k\) désigne une constante réelle fixée.

L'expression est-elle alors une proposition ou un prédicat ?
Reprendre la question précédente en supposant maintenant que \(k\) peut varier parmi les réels. Combien l'expression contient-elle alors de variables libres ?
Un prédicat \(P(x)\) est dit collectivisant en \(x\) si toutes les valeurs de \(x\) telles que la proposition \(P(x)\) est vraie constituent un ensemble. Dans ce cas cet ensemble est noté \begin{equation} \{x {\color{steelblue}\such} P(x)\}. \end{equation} on l'appelle ensemble en compréhension de \(P\). Le symbole \(\color{steelblue}\such\) se lit tel que. Dans le cas contraire, le prédicat est dit non collectivisant.

Cette définition peut sembler déroutante car naïvement nous envisageons toujours une collection d'objets comme un ensemble, que ces objets vérifient ou non un prédicat. Elle a pour objet de distinguer les prédicats qui définissent des ensembles des autres, cette fois formellement.

Les axiomes de la théorie des ensembles élaborée par Zermelo et Fraenkel fournissent une famille de prédicats col­lec­ti­vi­sants suf­fi­sam­ment riche pour pouvoir coder tous les objets dont les ma­thé­ma­ti­ciens ont besoin, mais contrôlent la construction de nouveaux ensembles afin de ne pas créer de mons­tres gé­né­rant des paradoxes.

De manière imagée, les axiomes et le langage de cette théorie s'apparentent à un jeu de construction dont les pièces détachées et les règles d'assemblage permettent de construire de nouveaux objets dont on peut étudier les propriétés. Pour valider cette boite de jeu, il fallait être capable de reconstruire*plus précisément coder au sens informatique du terme les objets utilisés depuis des lustres par les mathématiciens et montrer que le prix à payer pour cette restriction de mouvement constituait un gage de sécurité.

A contrario, la théorie ne fournit pas explicitement de prédicats non-collectivisants. Devraient être disqualifiés tous ceux dont les en­sem­bles associés, s'ils existaient, permettraient d'en déduire une contradiction. Cantor ne faisait pas ce distinguo et son principe d'abstraction affirmait que tout prédicat définissait un ensemble, ce que l'on traduirait dans le langage de la théorie ZF, par tout prédicat est collectivisant.

L'application du principe de Cantor, écarté dans la théorie ZF, génère des pa­ra­do­xes. Le plus célèbre d'entre eux est probablement le paradoxe de Russell * Bertrand Russell était un phi­lo­so­phe et ma­thé­ma­ti­cien ang­lais et l'un des fon­da­teurs de la lo­gi­que con­tem­po­rai­ne. Il a dé­cou­vert ce pa­ra­do­xe en 1901. : considérons le prédicat \(P(x)\) suivant :

\begin{equation} \label{eq:predicatRussell} \neg(x \in x). \end{equation}

Supposons que \(P(x)\) soit collectivisant en \(x\). Alors l'ensemble en compréhension de \(P\) existe :

\begin{equation} \label{eq:Russell} X:=\{x\such \neg(x \in x)\}. \end{equation}

D'après la définition \((\ref{eq:Russell})\) de l'ensemble \(X\), il est clair que si \(X\in X\) alors \(X\) satisfait \(\neg(X\in X)\). En notant \(A\) la proposition \(X\in X\), on vient donc de montrer que \[(A\then\neg A)\equiv (\neg A\lor \neg A)\equiv \neg A.\] Bien sûr, si \(\neg(X \in X)\), alors l'ensemble \(X\) satisfait le prédicat \((\ref{eq:predicatRussell})\) et doit donc appartenir à \(X\), on a donc montré que \[(\neg A\then A)\equiv (A\lor A)\equiv A.\] On a donc prouvé que \(A\land \neg A\) ce qui est contradictoire.

La théorie des ensembles avait pour principal objectif de s'assurer que ce nouveau langage ma­thé­ma­ti­que n'aboutirait jamais plus à des contradictions. Mal­heu­reu­se­ment le logicien autrichien Kurt Gödel a mis fin à cet espoir en démontrant en 1931 que dans toute théorie ma­thé­ma­ti­que cohérente et suffisamment riche pour coder l'ari­thmé­ti­que, il existe des propositions in­dé­ci­da­bles, c'est-à-dire qu'il n'existe aucune preuve qu'elles sont vraies ni qu'elles sont fausses dans cette théorie*Ce qui ne signifie pas que ces mêmes propositions exprimées dans une autre théorie des ensembles le res­te­raient. (dans le cas contraire une proposition est dé­ci­da­ble). D'autre part une théorie ma­thé­ma­ti­que (cohérente et suffisamment riche) ne permet pas de prouver sa propre cohérence, c'est-à-dire qu'elle ne permet pas de prouver qu'elle n'engendre pas des paradoxes.

Il faut également noter que parmi tous les prédicats non-collectivisants de la théorie ZF, tous ne génèrent pas nécessairement des paradoxes, des logiciens travaillent sur d'autres théories des ensembles moins strictes que la théorie ZF pour tenter de déverrouiller des questions qui y sont indécidables.

Les con­sé­quen­ces des travaux de Gödel ont un impact tout aussi dé­vas­ta­teur en in­for­ma­ti­que, c'est ce que vous étudierez dans un cours de cal­cu­la­bi­li­té.

Quantificateurs et ensembles

En pratique, la variable \(x\) décrit généralement des éléments d'un ensemble fixé \(X\), on utilise alors très souvent les quantifications bornées suivantes : \begin{align} \label{eq:universel} \forall x\in X\ \ &Q(x)\ \ \equiv\ \ \forall x\ {\color{#08F}(x\in X)\then Q(x)},\\ \label{eq:existentiel} \exists x\in X\ \ &Q(x)\ \ \equiv\ \ \exists x\ {\color{#F80}(x\in X)\land Q(x)}. \end{align}

La première expression a été construite sur la base de l'expression \((\ref{eq:universel0})\) avec le prédicat \({\color{#08F}(x\in X)\then Q(x)}\), la seconde sur la base de l'expression \((\ref{eq:existentiel0})\) avec le prédicat \({\color{#F80}(x\in X)\land Q(x)}\). Comme leurs homologues non bornées, ce sont bien des propositions et non des prédicats : la variable \(x\) y reste muette, au sens déjà précisé.

Pour se convaincre que les expressions à droite des équivalences logiques dans \((\ref{eq:universel})\) et \((\ref{eq:existentiel})\) sont bien des propositions et pas des prédicats, on peut les considérer respectivement comme des conjonctions et des disjonctions de propositions. Ainsi, le quantificateur universel (resp. existentiel) code la conjonction (resp. disjonction) des propositions obtenues pour chacune des instances de la variable quantifiée.

Par exemple la proposition \(\color{#08F}\forall x\in\{a,b,c\}\ P(x)\) résume bien la conjonction des trois propositions \[ {\color{#08F}\forall x\in\{a,b,c\}\ P(x)}\;\equiv\; {\color{#08F}P(a)\land P(b)\land P(c)}. \] et la proposition \(\color{#F80}\exists x\in\{1,2,3,4\}\ Q(x)\) résume la disjonction des quatre propositions \[ {\color{#F80}\exists x\in\{1,2,3,4\}\ Q(x)}\;\equiv\; {\color{#F80} Q(1)\lor Q(2)\lor Q(3)\lor Q(4)}. \] Mais la puissance de ces quantificateurs ne se limite pas à résumer un nombre fini de propositions, elles permettent surtout de s'affranchir de la finitude de \(X\) comme dans l'expression \(\forall x\in\R\).

Pour démontrer une proposition du type \(\forall x\in X\ \ P(x)\), on se donne un élément \(x\) quelconque de l'en­sem­ble \(X\) et on montre que \(P(x)\) est vraie. Comme \(x\) est quelconque, il incarne n'importe quel élé­ment de \(X\). Ainsi si la proposition \(P(x)\) est vraie, elle l'est aussi pour tout autre élément de \(X\).

Pour démontrer une proposition de la forme \(\forall x\in X\ \ P(x)\), on peut également décomposer l'ensemble \(X\) en parties deux-à-deux disjointes (une par­ti­tion de l'ensemble \(X\)) et faire une démonstration adaptée pour chacune de ces parties. On parle alors de preuve par disjonction de cas, la disjonction portant sur l'appartenance de \(x\) à l'une ou l'autre des parties de \(X\).

Pour démontrer une proposition du type \(\exists x\in X\ \ P(x)\), il faut exhiber un élément particulier \(x\) de l'en­sem­ble \(X\) tel que \(P(x)\) soit vraie, il peut d'ailleurs en exister plusieurs.

Il arrive souvent que l'on ait besoin d'exprimer l'existence d'un objet et que celui-ci est unique. On rajoute alors un point d'exclamation à la suite du quantificateur existentiel pour le signifier. La proposition \(\exists!\, x\in X\ P(x)\) est logiquement équivalente à la proposition \begin{equation} \underbrace{(\exists x\in X\ \ P(x))}_{\text{existence}}\;\land\;\underbrace{\Big(\forall x\in X\ \forall y\in X\ \ \big((P(x)\land P(y))\Rightarrow (x=y)\big)\Big)}_{\text{unicité}}. \end{equation} Le terme gauche de cette conjonction code l'existence de \(x\) et le terme droit son unicité en exprimant sous forme contraposée que deux éléments distincts \(x\) et \(y\) de l'ensemble \(X\) ne peu­vent simultanément satisfaire le prédicat : \[(x\neq y)\then \neg(P(x)\land P(y)).\]

La négation des deux expressions \((\ref{eq:universel0})\) et \((\ref{eq:existentiel0})\) est conforme à celle des énoncés cor­res­pon­dan­ts en langue na­tu­rel­le :

\begin{align*} \neg (\forall x\ P(x))&\equiv \exists x\ \neg P(x)\\ \neg (\exists x\ P(x))&\equiv \forall x\ \neg P(x) \end{align*} avec pour déclinaisons sur un ensemble \(X\) : \begin{align} \label{eq:negA} \neg ({\color{orange}\forall x\in X\ P(x)})&\;\;\equiv\;\,{\color{green}\exists x\in X\ \neg P(x)}\\ \label{eq:negE} \neg ({\color{#F6B}\exists x\in X\ P(x)})&\;\;\equiv\;\, {\color{lightgreen}\forall x\in X\ \neg P(x)} \end{align}
Soit \(X\) un ensemble et \(P(x)\) un prédicat de la variable \(x\) définie sur \(X\).
Démontrez les équivalences logiques \((\ref{eq:negA})\) et \((\ref{eq:negE})\).
En partant de \((\ref{eq:universel})\), on a  : \begin{align*} \neg(\forall x\in X\ \ P(x))\ &\ \equiv\neg(\forall x\ \ (x\in X)\ \Rightarrow\ P(x))\\ &\ \equiv\neg(\forall x\ \ \neg(x\in X)\ \lor\ P(x))\\ &\ \equiv\exists x\ \ (x\in X)\ \land\ \neg P(x)\\ \text{et finalement}\quad \neg(\forall x\in X\ \ \ P(x))&\ \equiv\ \exists x\in X\ \ \neg P(x)\\ \end{align*} De la même manière, en partant de \((\ref{eq:existentiel})\) on obtient : \begin{align*} \neg(\exists x\in X\ \ P(x))\ &\ \equiv \neg(\exists x\ (x\in X)\land P(x))\\ &\ \equiv \forall x\ \neg((x\in X)\land P(x))\\ &\ \equiv \forall x\ \neg(x\in X)\lor \neg P(x)\\ &\ \equiv \forall x\ (x\in X)\Rightarrow \neg P(x)\\ \text{et finalement}\quad \neg(\exists x\in X\ \ P(x))\ &\ \equiv\ \forall x\in X\ \ \neg P(x)\\ \end{align*}
On considère les trois expressions suivantes : \[ x+1>0,\qquad \forall x\,(x+1>0),\qquad \exists x\,(x^2=2). \]
Indiquez lesquelles sont des propositions.
Dans l'équation \(ax+b=0\), expliquez quel rôle jouent les symboles \(a\), \(b\) et \(x\) lorsque \(a\) et \(b\) sont supposés fixés.

Interprétations des formules prédicatives

Les langages mathématiques étant des supports pour objectiver la pensée, il est important de savoir interpréter ces nouvelles expressions et de réaliser que les manipulations logiques sont cohérentes par rapport à ces interprétations.

Illustrons l'équivalence logique \((\ref{eq:negA})\) en langue naturelle en supposant que \(X\) désigne l'ensemble des étudiants qui suivent ce cours de mathématiques et \(P(x)\) le prédicat dont l'interprétation est L'étudiant \(x\) comprend le cours. La proposition \({\color{orange}\forall x\in X\ P(x)}\) dans le membre gauche de l'équivalence logique \((\ref{eq:negA})\) s'interprète donc :

Tous les étudiants qui suivent ce cours le comprennent

Et sa négation pourrait être interprétée par Il existe un étudiant qui suit ce cours et ne le comprend pas plutôt que Tous les étudiants qui suivent ce cours ne le comprennent pas qui peut prêter à interprétation, veut-on signifier qu'aucun étudiant ne comprend le cours ou que certains étudiants ne le comprennent pas ? Et l'ambiguïté des langues na­tu­rel­les ne s'arrête pas là, le mot un induit souvent l'unicité, il est donc préférable d'exprimer la négation par

Il existe au moins un étudiant qui suit ce cours et qui ne le comprend pas

Ainsi, quand on veut démontrer qu'une pro­po­si­tion du type \(\color{orange}\forall x\in X\ \ P(x)\) est fausse, autrement dit que sa négation est vraie, il suffit d'exhiber un élément \(\color{green}x\in X\) tel que \(\color{green}\neg P(x)\), qu'on appelle un contre-exemple.

Étudions à présent l'équivalence logique \((\ref{eq:negE})\). En supposant que \(X\) désigne cette fois l'ensemble des éléphants, et que le prédicat \(P(x)\) soit L'éléphant \(x\) est rose, alors la proposition \({\color{#F6B}\exists x\in X\ P(x)}\) qui apparaît dans le membre gauche de l'équivalence logique \((\ref{eq:negE})\) s'interprète :

Il existe un éléphant rose

Et sa négation pourrait être la proposition il n'existe pas d'éléphants roses ou encore tous les éléphants ne sont pas roses, mais cette dernière laisse entendre que certains peuvent l'être mais pas tous ! Ma­thé­ma­ti­quement, on dirait quel que soit l'éléphant, celui-ci n'est pas rose ce qui s'exprime plus élégamment sous la forme

Aucun éléphant n'est rose.
Le langage ma­thé­ma­ti­que ne peut laisser la place qu'à une seule interprétation. Ces différents énoncés montrent au passage que la variable \(x\) est bien muette, nous ne l'avons jamais mentionnée pour exprimer \((\ref{eq:negA})\) ni \((\ref{eq:negE})\).

La langue française est truffée de chausse-trappes, et il est très facile de faire un faux raisonnement en lui donnant l'apparence de justesse, on parle alors de sophisme (ce que ne manquent jamais de faire les po­li­ti­ciens) ou de paralogisme quand c'est involontaire.

Ordre des quantificateurs

Les difficultés commencent quand on manipule des prédicats de plu­sieurs variables et que l'on quantifie tout ou partie de leurs variables. Par exemple, un prédicat \(P(x,y)\) dont la variable \(x\) a été quantifiée est un prédicat de la variable \(y\). Considérons le prédicat \(P(x,y)\) suivant défini sur deux variables réelles \(x\) et \(y\) : \[x^2-y= 1\] On peut définir le prédicat \(Q(x)\) de la variable \(x\) suivant \[\exists y\in\R\quad x^2-y= 1\] et la proposition \(\forall x\in\R\ Q(x)\), soit \[\forall x\in\R\ (\exists y\in\R\quad x^2-y = 1)\] que l'on écrit souvent en omettant les parenthèses : \begin{equation}\label{eq:AE} \forall x\in\R\ \exists y\in\R\quad x^2-y = 1. \end{equation} Cette proposition est vraie. En effet, quelle que soit la valeur du nombre réel \(x\), le nombre réel \(y\) défini par \(y:=x^2-1\) satisfait l'équation de la proposition \((\ref{eq:AE})\). Échangeons à présent les deux quantificateurs et étudions la signification de cette nouvelle proposition : \[\exists y\in\R\ \forall x\in\R\quad x^2-y = 1.\] Replaçons tout d'abord les parenthèses (ce n'est qu'une fois que ces écritures seront familières que l'on pourra s'en dispenser) : \begin{equation}\label{eq:EA} \exists y\in\R\ (\forall x\in\R\quad x^2-y = 1). \end{equation} Montrons que cette nouvelle proposition est fausse. Notons \(y_0\) un nombre réel \(y\) tel que tout nombre réel \(x\) satisfait l'égalité de la proposition \((\ref{eq:EA})\). Si tous les nombres réels \(x\) satisfont l'égalité \((\ref{eq:EA})\) pour \(y:=y_0\), c'est le cas en particulier des nombres réels \(0\) et \(1\). On peut donc affirmer que : \begin{align*} 0^2-y_0&=1^2-y_0 \end{align*} proposition équivalente à la proposition (prouvez le) : \begin{align*} 0=1 \end{align*} qui est fausse. Nous avons exhibé là un contre-exemple.

Il faut donc prendre garde à l'ordre des quantificateurs et en particulier replacer les parenthèses absentes si l'on doit pro­pager une négation comme \((\ref{eq:negA})\) ou \((\ref{eq:negE})\) pour des prédicats à plu­sieurs variables.

On dit qu'une fonction \(f:\R\rightarrow\R\) définie sur \(\R\) est simplement continue en un point \({\color{#FF8}x}\in\R\) si la pro­po­si­tion sui­van­te est satisfaite : \begin{equation} \label{eq:continuitesimple} \forall\varepsilon>0\quad\exists\delta\gt 0\quad\forall y\in \R\quad |{\color{#FF8}x}-y|\lt\delta\Rightarrow |f({\color{#FF8}x})-f(y)| \lt \varepsilon. \end{equation} Si l'on comprend que \(|x-y|\) désigne la distance de \(x\) à \(y\), cette proposition exprime formellement l'idée que l'on peut toujours cantonner l'image \(f(y)\) dans un rayon arbitraire \(\epsilon\) autour de l'image \(f(x)\), à condition de limiter les déplacements de \(y\) autour de \(x\) dans un rayon \(\delta\) qui dépend du rayon \(\epsilon\) que l'on s'est fixé.
Dessinez le graphe de la fonction \(f\) définie par \(x\mapsto x^2-3\) et illustrez sur ce graphe la continuité ou non-continuité de cette fonction en \(x=2\). Faites de même avec la fonction définie par \(x\mapsto 2x\) si \(x\leqslant 2\) et \(x\mapsto x\) si \(x > 2\).
Quelle proposition doit satisfaire une fonction \(f:\R\rightarrow\R\) pour qu'elle soit simplement continue en tout point \(x\in\R\) ?

Une fonction \(f:\R\rightarrow\R\) est uniformément continue sur \(\R\) si elle satisfait la proposition :

\begin{equation} \label{eq:continuiteuniforme} \forall\varepsilon\gt 0\quad\exists\delta \gt 0\quad\forall x\in \R\quad\forall y\in \R\quad |x-y| \lt \delta\Rightarrow |f(x)-f(y)| \lt \varepsilon. \end{equation}
Quelle différence remarquez-vous entre la continuité simple et la continuité uniforme ?
Écrivez la négation des deux propositions (\ref{eq:continuitesimple}) et (\ref{eq:continuiteuniforme}).
Soit \(X\) un ensemble et \(P(x)\) et \(Q(x)\) deux prédicats.
Écrivez la négation des deux propositions suivantes : \begin{align*} \forall x\in X&\quad P(x)\Rightarrow Q(x),\\ \exists x\in X&\quad P(x)\Rightarrow Q(x). \end{align*}

Poursuivons nos investigations sur l'ordre des quantificateurs en considérant l'énoncé suivant : \(f\) est une application constante de l'ensemble des réels dans lui-même*Nous ne verrons la définition d'une application qu'au chapitre Relations, applications, mais l'étudiant a déjà été familiarisé avec cet outil ma­thé­ma­ti­que en cours d'analyse. Notons simplement que l'ensemble des applications d'un ensemble \(X\) dans un ensemble \(Y\) est noté \(Y^X\).. On peut traduire la constance de l'application en logique des prédicats et reformuler cet énoncé :

L'application \(f\in\R^{\R}\) vérifie la proposition \begin{equation} \label{eq:marmite0} \forall (x_1,x_2)\in\R\times\R\ \ f(x_1)=f(x_2) \end{equation}

Dans ce cours, on condensera parfois un tel énoncé dans le métalangage mathématique en : \begin{equation*} f\in\R^\R:\quad \forall (x_1,x_2)\in\R\times\R\quad f(x_1)=f(x_2) \end{equation*}

On peut écrire une proposition équivalente à la proposition \((\ref{eq:marmite0})\) : \begin{equation} \label{eq:marmite} {\color{#88F}\exists c\in\R}\ \ {\color{orange}\forall x\in\R}\quad f(x)=c \end{equation}

qui n'est pas logiquement équivalente à la proposition \begin{equation} \label{eq:marmite2} {\color{orange}\forall x\in\R}\ \ {\color{#88F}\exists c\in\R}\quad f(x)=c \end{equation}

Cette dernière proposition exprime que tout nombre réel \(x\) admet une image \(c\) dans \(\R\) par \(f\) qui dépend donc de \(x\). Elle est toujours vraie puisque c'est précisément celle qui caractérise une application. La différence est de taille, \((\ref{eq:marmite})\) exprime que l'application \(f\) est constante, alors que \((\ref{eq:marmite2})\) répète qu'il s'agit d'une application…

La métaphore suivante devrait aider à comprendre l'impact d'une permutation des deux quantificateurs. Considérons l'expression fran­çai­se Toute marmite a son couvercle. En notant \(M\) l'ensemble des marmites, \(C\) l'ensemble des cou­ver­cles et \(P(m,c)\) le prédicat à deux variables dont l'interprétation est \(P(m,c)\) est vrai si et seulement si le couvercle \(c\) est adapté à la marmite \(m\), la proposition suivante a exactement la même structure que celle de la proposition \((\ref{eq:marmite2})\) : \begin{equation*} {\color{orange}\forall m\in M}\ \ {\color{#88F}\exists c\in C}\quad P(m,c) \end{equation*}

Il est évident que le couvercle \(c\) dépend de la mar­mi­te \(m\) considérée. En permutant les quantificateurs, la pro­po­si­tion \begin{equation*} {\color{#88F}\exists c\in C}\ \ {\color{orange}\forall m\in M}\quad P(m,c) \end{equation*} exprime qu'il existe un couvercle qui convient à toutes les marmites, ce qui n'est bien sûr pas la même chose.

Une proposition toujours vraie n'est pas pour autant une tautologie : ce mot est réservé à la strate logique. Une tautologie est vraie par sa seule forme : en remplaçant chacune de ses sous-formules atomiques ou quantifiées par une variable propositionnelle, on retrouve une tautologie du chapitre précédent. Ainsi \(P(x)\lor\neg P(x)\), de forme \(A\lor\neg A\), est une tautologie, quel que soit le sens donné à \(P\). La proposition \((\ref{eq:marmite2})\), elle, a pour forme une variable propositionnelle unique : sa forme ne garantit rien. Remplaçons d'ailleurs \(f(x)=c\) par un prédicat anonyme \(P(x,c)\) : la proposition \(\forall x\ \exists c\ P(x,c)\) n'a plus rien d'assuré, c'est exactement celle des marmites, et rien n'interdit qu'une marmite ait perdu son couvercle. La vérité de \((\ref{eq:marmite2})\) ne vient donc pas de la logique mais de la définition d'une application : c'est un théorème, pas une tautologie. De même, le mot antilogie est réservé aux propositions fausses par leur seule forme.
On considère les énoncés suivants :
  1. \(f\) est l'application identité du plan réel dans lui-même.
  2. \(f\) est une application du plan réel dans lui-même qui admet un point fixe.
  3. \(f\) est une application de l'ensemble des réels dans lui-même et l'équation \(f(x)=0\) admet une unique solution.
  4. \(f\) et \(g\) sont des applications de l'ensemble des réels dans lui-même et \(f\) est strictement supérieure à \(g\).
  5. \(f\) est une application paire de l'ensemble des réels dans lui-même.
  6. \(f\) est une application paire de l'ensemble des réels dans lui-même strictement décroissante sur \(R^+\).
  7. \((u_n)_{n\in\N}\) est une suite réelle bornée.
  8. \((u_n)_{n\in\N}\) est une suite réelle croissante.
  9. \((u_n)_{n\in\N}\) est une suite réelle constante à partir d'un certain rang.
  10. \((u_n)_{n\in\N}\) est une suite réelle périodique.
  11. \((u_n)_{n\in\N}\) est une suite réelle ultimement périodique.
Exprimez ces énoncés en logique des prédicats.
Exprimez leur négation en logique des prédicats.
Comme tous les énoncés en langue naturelle, il peut y avoir des ambiguïtés donnant lieu à des interprétations différentes, et par conséquent à différentes formalisations. Dans chacun des différents énoncés, il est implicite que l'on s'intéresse à un objet appartenant à un ensemble particulier et qui vérifie une certaine propriété.

Dans ce cas, pour le premier énoncé \(f\) est l'application identité du plan réel dans lui-même, on écrirait que \(f\in{(\R\times\R)}^{\R\times\R}\) et que cette application satisfait la proposition \[\forall(x,y)\in\R\times\R\ f((x,y))=(x,y)\] ce que l'on condense parfois en une expression (informelle) \begin{equation*} f\in{(\R\times\R)}^{\R\times\R}:\ \forall(x,y)\in\R\times\R\ f((x,y))=(x,y). \end{equation*} en séparant la donnée de la proposition qu'elle vérifie.

On a donc avec les abus de langage usuels : \begin{align*} 1.\ & f\in{(\R^2)}^{\R^2} : \forall (x,y)\in\R^2\ \ f(x,y)=(x,y)\\ 2.\ & f\in{(\R^2)}^{\R^2} : \exists (x,y)\in\R^2\ \ f(x,y)=(x,y)\\ 3.\ & f\in{\R}^{\R} : \exists! x\in\R\ \ f(x)=0\\ 4.\ & (f,g)\in({\R}^{\R})^2 : \forall x\in\R\ \ f(x) > g(x)\\ 5.\ & f\in{\R}^{\R} : \forall x\in\R\ \ f(x)=f(-x)\\ 6.\ & f\in{\R}^{\R} : (\forall x\in\R\ \ f(x)=f(-x))\land (\forall (x,y)\in(\R^+)^2\ \ x \lt y \Rightarrow f(x)\gt f(y))\\ 7.\ & (u_n)_{n\in\N}\in{\R}^{\N} : \exists B\in\R\ \forall n\in\N\ \ |u_n|\leqslant B\\ 8.\ & (u_n)_{n\in\N}\in{\R}^{\N} : \forall (n,m)\in\N^2\ \ n\leqslant m \Rightarrow u_n\leqslant u_m\\ 9.\ & (u_n)_{n\in\N}\in{\R}^{\N} : \exists N\in\N\ \exists c\in\R\ \forall n\in\N\ \ n \gt N \Rightarrow u_n=c\\ 10.\ & (u_n)_{n\in\N}\in{\R}^{\N} : \exists k\in\N^*\ \forall n\in\N\ \ u_{n+k}=u_n\\ 11.\ & (u_n)_{n\in\N}\in{\R}^{\N} : \exists k\in\N^*\ \exists N\in\N\ \forall n\in\N\ \ n\geqslant N\then u_{n+k}=u_n \end{align*}
Leurs négations : \begin{align*} 1.\ & f\in{(\R^2)}^{\R^2} : \exists (x,y)\in\R^2\ \ f(x,y)\neq(x,y)\\ 2.\ & f\in{(\R^2)}^{\R^2} : \forall (x,y)\in\R^2\ \ f(x,y)\neq(x,y)\\ 3.\ & f\in{\R}^{\R} : (\forall x\in\R\ \ f(x)\neq 0)\lor(\exists(x,y)\in\R^2\ (x\neq y)\land (f(x)=0)\land (f(y)=0))\\ 4.\ & (f,g)\in({\R}^{\R})^2 : \exists x\in\R\ \ f(x) \leqslant g(x)\\ 5.\ & f\in{\R}^{\R} : \exists x\in\R\ \ f(x)\neq f(-x)\\ 6.\ & f\in{\R}^{\R} : (\exists x\in\R\ \ f(x)\neq f(-x))\lor (\exists (x,y)\in(\R^+)^2\ \ (x \lt y) \land (f(x)\leqslant f(y)))\\ 7.\ & (u_n)_{n\in\N}\in{\R}^{\N} : \forall B\in\R\ \exists n\in\N\ \ |u_n| \gt B\\ 8.\ & (u_n)_{n\in\N}\in{\R}^{\N} : \exists (n,m)\in\N^2\ \ (n\lt m)\land (u_n \gt u_m)\\ 9.\ & (u_n)_{n\in\N}\in{\R}^{\N} : \forall N\in\N\ \forall c\in\R\ \exists n\in\N\ \ (n \gt N) \land (u_n\neq c)\\ 10.\ & (u_n)_{n\in\N}\in{\R}^{\N} : \forall k\in\N^*\ \exists n\in\N\ \ u_{n+k}\neq u_n\\ 11.\ & (u_n)_{n\in\N}\in{\R}^{\N} : \forall k\in\N^*\ \forall N\in\N\ \exists n\in\N\ \ (n\geqslant N)\land (u_{n+k}\neq u_n) \end{align*}

Axiomes de la théorie ZF

Nous allons à présent introduire la terminologie de base de la théorie des ensembles et définir pas-à-pas les opérations élémentaires sur les ensembles. On commence par l'inclusion.

Certains axiomes peuvent paraître déroutants tant ce qu'ils affirment paraît évident. Leur rôle est précisément d'intégrer ces évidences, ou ces résultats qui nous semblent naturels dans la théorie. Cela sous-entend souvent que l'on ne peut pas établir ces résultats autrement.

Axiome d'extension

En théorie des ensembles, le symbole d’égalité = est un symbole logique primitif dont le rôle est d’exprimer la possibilité de remplacer un terme par un autre dans toute formule sans modifier sa valeur de vérité, mais il ne dit rien sur ce que signifie, pour des ensembles, d'être égaux. Nous devons donc préciser ce que cette égalité logique représente.

Soit \(X\) et \(Y\) deux ensembles. On dit que \(X\) est inclus dans \(Y\) ou que \(X\) est une partie de \(Y\) ou encore que \(X\) est un sous-ensemble de \(Y\), ce que l'on note \(X\subseteq Y\) ou \(Y\supseteq X\) si et seulement si \begin{equation*} \forall x\quad x\in X\then x\in Y. \end{equation*}

Attention aux confusions possibles à cause des différences d'acception d'un mot en langue naturelle et en mathématiques. En français, l'inclusion est synonyme d'appartenance, alors que l'inclusion \(\subseteq\) et l'appartenance \(\in\) ne signifient pas la même chose en théorie des ensembles.

On note commodément \(X\not\subseteq Y\) plutôt que \(\neg(X\subseteq Y)\). Dans la proposition \(X\) est une partie de \(Y\), il n'y a plus mention de la variable \(x\) présente dans son homologue formalisée \(\forall x\ \ x\in X\then x\in Y\), elle est donc bien muette.

L'axiome d'extension exprime que deux en­semb­les sont égaux si et seulement s'ils ont exactement les mêmes éléments. Il relie la notion logique d’égalité (pure substitution) à la conception mathématique de l’égalité entre ensembles (égalité des contenus). Il permet ainsi d’interpréter correctement le symbole = dans le cadre de la théorie ZF.

Soit \(X,Y\) deux ensembles. Alors \(X=Y\) si et seulement si \begin{equation} \label{eq:egaliteensembles} (X\subseteq Y)\land (Y\subseteq X). \end{equation}

C'est cet axiome que l'on applique quand on veut démontrer que deux ensembles \(X\) et \(Y\) sont égaux, on parle souvent de la double inclusion. Cela consiste à se donner un élément quelconque \(x\in X\) et à démontrer qu'il appartient à l'ensemble \(Y\), puis à démontrer la réciproque.

Axiome de la paire

Si l'on dispose de deux objets \(a\) et \(b\), l'axiome de la paire assure l'existence de l'ensemble constitué de ces deux objets.

Soit \(a\) et \(b\) deux objets. Le prédicat \((x=a)\lor(x=b)\) est col­lec­ti­vi­sant en \(x\). Son ensemble en compréhension existe, il est noté \[\{a,b\}:=\{x\such (x=a)\lor(x=b)\}\] et on l'appelle paire \(\{a,b\}\).

Dans le cas où \(a=b\), la paire \(\{a,b\}\) est réduite à \(\{a\}\), on l'appelle singleton \(a\). L'axiome de la paire nous permet de considérer un ensemble avec deux objets et c'est grâce à cet axiome et à l'axiome de la réunion plus loin, que l'on peut définir l'écriture en extension d'un ensemble.

Axiome de sélection

L'axiome de sélection (ou axiome de compréhension ou encore axiome de séparation) est déjà bien connu du lecteur après le cours de mathématiques générales, il est utilisé en permanence. C'est la restriction du principe d'abstraction de Cantor, tout prédicat \(P(x)\) définit un ensemble, à condition que les objets \(x\) qui vérifient \(P(x)\) soient sélectionnés dans un ensemble pré­exis­tant :

Soit \(X\) un ensemble et \(P(x)\) un prédicat. Le prédicat \((x\in X)\land P(x)\) est collectivisant en \(x\). Son ensemble en compréhension existe et on le note \begin{equation} \label{eq:compr} \{x\in X\such P(x)\}. \end{equation}

On peut donc collecter les éléments d'un ensemble \(X\) qui satisfont un prédicat quelconque \(P(x)\). Il est clair qu'il s'agit d'un sous-ensemble de \(X\). Ainsi, cet axiome est inoffensif, il ne permet pas de créer un ensemble trop gros. L'écriture \((\ref{eq:compr})\) d'un ensemble est dite écriture en comp­ré­hen­sion, ses éléments sont décrits via un prédicat qu'ils satisfont. De manière imagée, on peut interpréter \((\ref{eq:compr})\) comme le résultat d'une pêche au filet, \(X\) désigne la zone de pêche et le prédicat \(P(x)\) les caractéristiques du poisson à retenir dans le filet.

Nous verrons une autre écriture très commode des ensembles en compréhension une fois étudié les fonctions.

Axiome de la réunion

Cet axiome exprime simplement que si l'on dispose de plusieurs ensembles, on peut considérer l'ensemble qui contient tous leurs éléments.

Soit \(Y\) un ensemble. Le prédicat \(\exists X\ (X\in Y)\land(x\in X)\) est col­lec­ti­vi­sant en \(x\). Son ensemble en compréhension existe, on l'appelle réunion de \(Y\) et on le note \begin{equation}\label{eq:union} \displaystyle\bigcup_{X\in Y}X \end{equation}

Quand l'ensemble \(Y=\{A,B\}\) est une paire d'ensembles, sa réunion est notée \(A\cup B\). C'est grâce à l'axiome de la réunion et à l'axiome de la paire que l'on a pu construire l'ensemble \((\ref{eq:ens4})\), c'est la réunion des paires \(\{1,f\}\) et \(\{3,x\}\). La réunion de l'ensemble \(\{\{a\},\{a,b,d\},\{a,c\},\{b,d\}\}\) est l'en­sem­ble \(\{a,b,c,d\}\).

Soit \(X\) un ensemble. L'ensemble \(\{x\in X\such x\neq x\}\) existe et ne dé­pend pas de \(X\). On l'appelle l'en­sem­ble vide et on le note \(\varnothing\).
Soit \(X\) un ensemble et \(P(x)\) le prédicat \(x\not=x\). L'axiome de sélection assure l'existence de l'ensemble \(\varnothing_X:=\{x\in X\such P(x)\}\). Montrons qu'il ne dépend pas de \(X\). Considérons un ensemble \(Y\), et \(\varnothing_Y:=\{x\in Y\such P(x)\}\) construit de la même manière. Le prédicat \(P(x)\) : \(x\not=x\), ne convoque aucun symbole propre à la théorie des ensembles : il est toujours faux, quel que soit \(x\), sans qu'aucun ensemble n'ait besoin de le circonscrire. Pour tout \(x\), \(x\in\varnothing_X\) est donc fausse, ce qui montre \(\varnothing_X\subseteq\varnothing_Y\) ; on échange les rôles de \(X\) et \(Y\) pour obtenir l'inclusion réciproque. Nous venons donc de démontrer que \(\varnothing_X=\varnothing_Y\) (cf. axiome d'extension).

Soit \(P(x)\) un prédicat quelconque. En se souvenant de \((\ref{eq:universel})\) et \((\ref{eq:existentiel})\), on comprend pourquoi la proposition \(\forall x\in\varnothing\ P(x)\), qui affirme que tout élément de l'ensemble vide satisfait le prédicat \(P(x)\), est toujours vraie : elle s'écrit \(\forall x\ (x\in\varnothing)\then P(x)\) et, \(x\in\varnothing\) étant faux pour tout \(x\), chaque implication est vraie (on rappelle que \(\bot\then A\) est toujours vrai). Symétriquement, la proposition \(\exists x\in\varnothing\ P(x)\), qui s'écrit \(\exists x\ (x\in\varnothing)\land P(x)\), est toujours fausse. Ce ne sont pourtant ni une tautologie ni une antilogie : chaque instance \(x\in\varnothing\then P(x)\) a la forme \(A\then B\), qui n'est pas une tautologie, et \((x\in\varnothing)\land P(x)\) la forme \(A\land B\), qui n'est pas une antilogie. Leur valeur de vérité ne tient pas à leur forme, mais au fait que \(x\in\varnothing\) est faux pour tout \(x\), ce que nous avons établi dans la preuve précédente à partir de la définition même de l'ensemble vide.

Soit \(X\) et \(Y\) deux ensembles. La différence entre les ensembles \(X\) et \(Y\) est l'ensemble \(\{x\in X\such x\not\in Y\}\) noté \(X\setminus Y\). Si de plus \(Y\subseteq X\), alors \(X\setminus Y\) est appelé complémentaire de \(Y\) dans \(X\).

On note parfois \(\complement_XY\) le complémentaire de \(Y\) dans \(X\) ou encore \(\overline{Y}\) si le contexte discursif établit clairement quel est l'ensemble de référence \(X\).

\(X\setminus X=\varnothing\) et \(X\setminus\varnothing=X\) ou encore \(\{a,b\}\setminus\{a\}=\{b\}\).
Soit \(X\) et \(Y\) deux ensembles. L'in­ter­sec­tion des ensembles \(X\) et \(Y\), notée \(X\cap Y\) est l'ensemble défini par \(\{x\in (X\cup Y)\such (x\in X)\land (x\in Y)\}\).

Deux ensembles \(X\) et \(Y\) dont l'intersection \(X\cap Y=\varnothing\) est vide sont dits disjoints. En particulier l'ensemble vide est disjoint de tout ensemble \(X\). L'intersection d'un ensemble d'ensembles à la manière de la réunion d'un ensemble sera définie au chapitre prochain. La différence symétrique entre deux en­sem­bles \(X\) et \(Y\) est l'ensemble \((X\cup Y)\setminus(X\cap Y)\), on le note \(X\;\Delta\;Y\).

La réunion de deux ensembles disjoints est parfois notée \(A\sqcup B\).

Pour aider à la compréhension, on représente parfois les opérations ensemblistes à l'aide d'un dia­gram­me de Venn.* John Venn était un ma­thé­ma­ti­cien ang­lais du début du 20-ème siècle Les ensembles sont représentés sous forme de cercles ou de patates qui se che­vau­chent. Vous pouvez visualiser le résultat des différentes opérations ensemblistes en les sur­vo­lant ci-dessous :

X Y 1 3 5 7 2 4 6 8 9 11 13
Soit \(X:=\{x,2,A,x,1\}\) et \(Y:=\{x,A,1,3,0\}\). Calculez les ensembles \(X\setminus Y\), \(X\symdif Y\), \(X\cap Y\) et \(X\cup Y\).
Les deux ensembles \(X:=\{1,2,3,4\}\) et \(Y:=\{2,1,1,4,3,3\}\) sont-ils égaux ?

Axiome des parties

L'axiome des parties* nettement moins inoffensif que l'axiome de sélection permet de considérer l'ensemble dont les éléments sont tous les sous-ensembles de \(X\). Nous verrons au chapitre Combinatoire qu'il est considérablement plus grand que \(X\).

Soit \(X\) un ensemble. Le prédicat \(Y\subseteq X\) est collectivisant en \(Y\). Son ensemble en compréhension existe, on le note \(\parts{X}\) : \begin{equation} \parts{X}=\{Y \such Y\subseteq X\} \end{equation} Il est appelé ensemble des parties de \(X\).

L'ensemble vide est une partie de tout ensemble \(X\) puisque \(x\in\varnothing\then x\in X\) est une proposition vraie puisque \(x\in\varnothing\) est fausse. Un ensemble est bien sûr inclus dans lui-même, par conséquent l'ensemble des parties d'un ensemble \(X\) contient toujours la partie vide \(\varnothing\) et l'ensemble \(X\). Par exemple si \(X=\{a,b,c\}\), on a \[\parts{X}=\{\varnothing,\{a\},\{b\},\{c\},\{a,b\},\{a,c\},\{b,c\},X\}.\] D'autre part, l'ensemble des par­ties de l'ensemble vide \(\parts{\varnothing}=\{\varnothing\}\) qui n'est pas l'en­semb­le vide puisqu'il contient l'élément \(\varnothing\).

L'ordre dans lequel nous écrivons les éléments d'un ensemble en extension n'a pas d'importance, la paire \(\{x,y\}\) est donc égale à la paire \(\{y,x\}\). Comment définir un nouvel objet ma­thé­ma­ti­que similaire à une paire mais pour lequel l'ordre dans lequel on écrit les deux objets a une importance ? On admettra le résultat suivant.

Soit \(x\) et \(y\) deux objets. La paire \(\{\{x\},\{x,y\}\}\) est appelée couple \(x\), \(y\) noté \((x,y)\). Soit \(X\) et \(Y\) deux ensembles. L'en­sem­ble des couples \((x,y)\) tels que \(x\in X\) et \(y\in Y\) existe, on le note \(X\times Y\) et on l'appelle produit car­té­sien de \(X\) et \(Y\). Si \(c=(x,y)\), on définit \(\text{pr}_1(c):=x\) et \(\text{pr}_2(c):=y\) appelés première projection et deuxième projection de \(c\) respectivement.

On peut vérifier que deux couples sont égaux si et seulement si leurs projections respectives sont égales (cf. exercice suivant). Par conséquent on dispose d'un objet mathématique \((x,y)\) qui répond à notre besoin : il contient deux objets \(x\) et \(y\) et l'ordre dans lequel ils apparaissent est important, i.e. \((x,y)\neq(y,x)\). On peut bien sûr imaginer d'autres constructions ensemblistes pour définir un objet similaire. Il faut être conscient qu'il ne s'agit que d'un simple codage et que maintenant que ce nouvel objet élémentaire a intégré notre arsenal, on peut oublier l'échafaudage qui a permis sa cons­truc­tion.

Un ensemble \(G\) de couples est appelé graphe. On définit respectivement la première et la deuxième projection d'un graphe \(G\) : \begin{align*} \text{pr}_1(G)&:=\{\text{pr}_1(c)\such c\in G\}=\{x\such \exists (x,y)\in G\}\\ \text{pr}_2(G)&:=\{\text{pr}_2(c)\such c\in G\}=\{y\such \exists (x,y)\in G\}. \end{align*}

On généralise facilement la notion de couple à la notion de \(n\)-uplet \((x_1,x_2,\ldots,x_n)\) en posant \begin{equation} (x_1,\ldots,x_n):=((x_1,\ldots,x_{n-1}),x_n) \end{equation} et en utilisant inductivement l'axiome de la paire et l'axiome de la réunion puis en définissant le produit cartésien de \(n\) ensembles \(X_1, X_2,\ldots,X_n\) par \begin{equation} X_1\times X_2\times\cdots\times X_n:=\{(x_1,x_2,\ldots,x_n)\such \forall i\in\{1,\ldots,n\}\ x_i\in X_i\}. \end{equation} On définit alors la \(i\)-ème projection \(\text{pr}_i\) pour tout \(i\in\{1,\ldots,n\}\) et un ensemble \(G\) de \(n\)-uplets est qualifié de \(n\)-graphe.

Nous verrons au chapitre 4 la définition de l'écriture indicielle \(x_i\) parachutée par endroit depuis le début de ce cours. Nous verrons également que l'on peut définir les \(n\)-uplets de manière plus simple et plus générale à l'aide des familles d'éléments d'un ensemble, introduites au chapitre consacré aux relations.

Il est tout à fait normal que plusieurs constructions d’un même objet mathématique coexistent. En théorie des ensembles, il faut surtout voir celle-ci comme un système de codage cohérent des objets mathématiques, plutôt que comme une tentative de dire ce que ces objets sont vraiment.

Tout comme un langage de programmation permet de coder des objets complexes à l’aide de différentes combinaisons d’objets élémentaires, on peut coder les objets mathématiques de plusieurs façons, tant que les propriétés essentielles sont conservées.

On désigne par \(x\) et \(y\) deux éléments d'un ensemble donné. Démontrez que \[(x,y)=(x',y')\Rightarrow (x=x')\land(y=y').\]
À partir de l'ensemble vide \(\varnothing\), on peut construire inductivement les ensembles ci-dessous en définissant chaque nouvel ensemble à l'aide du précédent \(X\) par la réunion \(X\cup\{X\}\) :

\begin{equation} \begin{matrix} \varnothing & {\color{#FF8}\{\varnothing\}} &{\color{orange}\{\varnothing,{\color{#FF8}\{\varnothing\}}\}} &\{\varnothing,\{\varnothing\},{\color{orange}\{\varnothing,{\color{#FF8}\{\varnothing\}}\}}\} &\cdots\\ \{\,\}& \{0\}&\{0,1\}&\{0,1,2\}&\cdots\\ 0 & 1 & 2 & 3 &\cdots \end{matrix} \end{equation}

Cette ingénieuse construction assure que chaque ensemble est contenu dans le suivant, mimant ainsi grâce à l'inclusion \(\subseteq\) ensembliste l'ordre naturel sur les entiers \(\leqslant\). On identifie l'ensemble vide à \(0\) et chaque nouvel ensemble construit est identifié au nombre entier suivant : son cardinal. Ainsi les entiers naturels sont représentables au sein de cette théorie des ensembles. Ce codage des entiers naturels est dû au mathématicien John Von Neumann. L'axiome de l'infini assure que l'on peut tous les regrouper en un en­sem­ble, autrement dit que l'ensemble \(\N\) existe. Nous le re­trou­ve­rons au chapitre Combinatoire.

Axiome du choix

Un dernier axiome, et nous achèverons là cette introduction à la théorie des ensembles, l'axiome du choix. Il fait intervenir deux notions étudiées plus loin dans ce cours, la notion de fonction et la notion de famille d'éléments d'un ensemble, mais que l'étudiant connaît déjà. Cet axiome nous autorise à extraire un élément de notre choix de chaque ensemble d'une famille d'ensembles pour en faire un ensemble, une sorte de menu à la carte. Cet axiome peut être intégré ou non dans la théorie des ensembles, si c'est le cas elle est appelée théorie zfc.

Soit \((X_i)_{i\in I}\) une famille d'ensembles non vides. Il existe une fonction de choix \begin{equation*} f:I\;\rg\;\bigcup_{i\in I}X_i \end{equation*} telle que \(\forall i\in I\ f(i)\in X_i\).

Remarques finales

La liste d'axiomes présentée dans ce chapitre est volontairement incomplète. La théorie des ensembles moderne, dite ZF en hommage à Zermelo et Fraenkel, comprend deux axiomes supplémentaires – le schéma de remplacement et l'axiome de fondation – plus délicats, et dont l'usage courant des mathématiques peut se passer : tous les objets construits dans ce cours ne réclament que les axiomes présentés ici. Ces deux axiomes sont étudiés dans le cours de calculabilité de master, qui revient en détail sur les fondements de la théorie des ensembles.

Comme évoqué au chapitre précédent, le texte mathématique suit une structure fondamentale faite de définitions et de théorèmes, alternant avec des exemples, des remarques et des commentaires qui en éclairent le sens. Ce cours respecte cette organisation, tout en intégrant des explications pour en comprendre les motivations et les enjeux. À ce stade, il est essentiel de maîtriser la structure type d'une définition et d'un théorème :

Pour une définition d'un nouvel objet mathématique :

Pour un théorème :

Formalisation

Réponse au problème de la médiathèque

On rappelle qu'il s'agit d'étudier comment automatiser la recherche de documents qui satisfont la requête suivante dans une médiathèque : trouver tous les documents qui parlent de robot(s) ou de chat(s)*l’extraction des termes a permis de regrouper les variantes lexicales robot / robots ou encore chat / chats sous un même descripteur normalisé., mais qui ne mentionnent pas l'intelligence artificielle.

Le corpus \(\mathscr D\) de cette médiathèque est le suivant :

Définition des prédicats

On définit trois prédicats d'une variable \(d\) représentant un document avec les interprétations suivantes :

La requête exprimée par l’usager se traduit par le prédicat \(P(d)\) suivant sur le corpus \({\mathscr D}\) de documents de la médiathèque :

\[ P(d):\equiv(R(d) \lor C(d)) \land \neg I(d). \] et le sous-ensemble \({\mathscr D}(P)\) du corpus \({\mathscr D}\) de documents satisfaisant la requête \(P\) est donné par (via l'axiome de sélection) \[ {\mathscr D}(P)=\left\{d\in{\mathscr D}\such (\,R(d) \lor C(d)\,) \land \neg I(d)\right\}. \]

Calcul

Le travail à fournir se traduit à présent par de simples opérations ensemblistes

\(d\) \(R(d)\) \(C(d)\) \(I(d)\) \(P(d)\)
\(d_1\) ✕ ✓ ✕ ✓
\(d_2\) ✓ ✕ ✓ ✕
\(d_3\) ✓ ✓ ✕ ✓
\(d_4\) ✕ ✕ ✓ ✕
\(d_5\) ✓ ✕ ✕ ✓
\(d_6\) ✕ ✕ ✓ ✕
Interprétation des prédicats

Trois documents correspondent finalement à la requête \(P\) : \[ {\mathscr D}(P)=\{d_1,d_3,d_5\} \]

Perspectives d'automatisation du processus

Bien sûr, on est encore loin de pouvoir réaliser toutes ces opérations automatiquement. Comment sont indexés les termes clefs des documents ? Peut-on traduire automatiquement une requête en langue naturelle sous forme prédicative ? etc.

L’évaluation du prédicat \(P(d)\) sur le corpus \(\mathscr{D}\) repose sur un traitement algorithmique qui peut être schématiquement décomposé en plusieurs étapes :

  1. Indexation du corpus : Cette phase est réalisée au préalable pour tous les documents du corpus qui sont enrichis de descripteurs (les tag) sur lesquels les requêtes vont réellement opérer. Cette opération peut être réalisée manuellement par un professionnel à chaque nouveau document abondant le corpus. Pour des raisons évidentes, ce travail est désormais réalisé automatiquement, en particulier par des algorithmes de traitement des langues naturelles.
  2. Traduction de la requête : Lorsqu’une requête est soumise par l’utilisateur (sous forme textuelle), elle est tout d’abord transformée en une formule logique sur les prédicats correspondant aux descripteurs indexés (par exemple ici : \(P(d) \equiv (R(d) \lor C(d)) \land \neg I(d)\)). Cette traduction peut être réalisée manuellement pour des requêtes simples, ou bien automatiquement grâce à un analyseur syntaxique ou un parseur de requêtes, qui identifie les opérateurs logiques (et, ou, non) et les entités lexicales à relier aux tags du système.
  3. Filtrage du corpus : La requête logique ainsi obtenue est ensuite évaluée sur les descripteurs associés à chaque document. Cette étape consiste à appliquer la combinaison booléenne aux tags présents, sans nécessiter de lire à nouveau le contenu complet des documents. Les documents satisfaisant la requête sont alors extraits et restitués à l’utilisateur.

D’un point de vue calculatoire, cette procédure peut s’exprimer de façon élémentaire en Python sous la forme suivante :

  # 1. Indexation du corpus
  index = {
  "d1": {"chat"},
  "d2": {"robot", "ia"},
  "d3": {"robot", "chat"},
  "d4": {"ia"},
  "d5": {"robot"},
  "d6": {"ia"}
  }

  # 2. Traduction de la requête
  def P(d):
  tags = index[d]
  return ("robot" in tags or "chat" in tags) and ("ia" not in tags)

  # 3. Filtrage du corpus
  resultats = [d for d in index if P(d)]

  print(resultats)

Le résultat produit ici est :

  ['d1', 'd3', 'd5']

Ce qui correspond exactement à l’ensemble \({\mathscr D}(P)\).

Dans des systèmes de recherche documentaire de grande taille, ces opérations sont optimisées via :

L’exemple présenté ici illustre une version très simplifiée, mais conceptuellement fidèle aux principes sous-jacents des moteurs de recherche documentaires.

Le retour du Sudoku

Le calcul des prédicats permet de modéliser certains problèmes de manière beaucoup plus concise et expressive que le calcul propositionnel, notamment en évitant la prolifération des variables lorsque les domaines de valeurs sont importants. Revenons sur le jeu du Sudoku introduit dans le chapitre précédent. On rappelle qu'il faut comp­lé­ter les cases vierges d'une grille de \(9\times 9\) cases avec des valeurs comprises entre 1 et 9 de manière à ce que chacun des \(27\) blocs de \(9\) cases contienne exactement ces \(9\) valeurs, c'est-à-dire :

  1. 1 : Chaque ligne doit contenir exactement chacune des 9 valeurs 1 à 9 ;
  2. 2 : Chaque colonne doit contenir exactement chacune des 9 valeurs 1 à 9 ;
  3. 3 : Chaque région \(3 \times 3\) doit contenir exactement chacune des 9 valeurs 1 à 9.

Les valeurs déjà présentes dans la grille, ont été choisies de manière à ce qu'il n'existe qu'une seule façon de compléter la grille, et le jeu consiste à les trouver. La grille ci-dessous est un exemple de grille à résoudre.

La formalisation du problème du Sudoku se fait avec un langage adapté. Les constantes sont les \(9\) valeurs de l'ensemble \({\mathscr C}:=\{1,2,3,\ldots,9\}\) et on considère des prédicats \(S(l,c,n)\) à \(3\) variables dans l'ensemble \(\def\CC{{\mathscr C}}\CC\) avec l'interprétation suivante :

\(S(l,c,n)\) est vrai si et seulement si la case à la ligne d'indice \(l\) et à la colonne d'indice \(c\) contient la valeur \(n\).

C'est bien plus économique que la logique propositionnelle avec laquelle il fallait définir une variable propositionnelle pour chaque valeur possible dans chaque case, soit \(9\times 9\times 9=729\) va­riab­les.

On traduit le fait que chaque case contient exactement une valeur par les deux propositions sui­van­tes (la première pour exprimer au moins une valeur, la seconde pour au plus une valeur) :

\begin{align*} &{\color{#88F}\forall (l,c)}\in\CC^2\ {\color{orange}\exists n}\in\CC\quad S(l,c,n),\\ &{\color{#88F}\forall (l,c)}\in\CC^2\ {\color{#FF8}\forall(n,n')}\in\CC^2\quad S(l,c,n)\land S(l,c,n')\then {\color{#FF8}n=n'}. \end{align*}

La partie des règles R1 et R2 disant que chaque nombre apparaît une seule fois par ligne et par colonne s'exprime respectivement par les deux propositions suivantes :

\begin{align*} &\forall n\in\CC\ \forall l\in\CC\ \forall(c,c')\in\CC^2\quad S(l,c,n)\land S(l,c',n)\then c=c',\\ &\forall n\in\CC\ \forall c\in\CC\ \forall (l,l')\in\CC^2\quad S(l',c,n)\land S(l,c,n)\then l=l'. \end{align*}

Pour la partie de la règle R3 disant que chaque nombre apparaît au plus une fois par région, c'est un peu plus complexe car les sous-grilles \(3\times 3\) ne sont pas aisément adressables par des indices séparés. On peut régler ce problème de bien des manières. Par exemple en introduisant une fonction auxiliaire \(r:\CC^2\rightarrow\CC\) qui à chaque couple \((l,c)\) associe le numéro de la région où se trouve la case à la ligne \(l\) et à la colonne \(c\), en numérotant les régions de \(1\) à \(9\) dans l'ordre de lecture par exemple. On aurait alors

\begin{align*} &\forall (l,l',c,c',n)\in\CC^5\quad S(l,c,n)\land S(l',c',n)\land r(l,c)=r(l',c')\then (l,c)=(l',c'). \end{align*}

Chacun des \(24\) indices fournis dans la grille au départ se traduit par une instanciation \(S(l,c,n) = V\) pour la valeur \(n\) affectée à la ligne \(l\) et la colonne \(c\), par exemple ici \(S(2,5,2)=V\) ou encore \(S(3,7,5)=V\).

La théorie de la démonstration et l'intelligence ar­ti­fi­ciel­le développent des techniques pour répondre à des problèmes de cette nature en formalisant le langage du raisonnement. Le langage Prolog dont la première version est parue en 1972 (et qui est toujours disponible), a été l'un des précurseurs sur la résolution de problèmes logiques en logique des prédicats.
On cherche à placer \(8\) reines sur un échiquier sans qu'elles se mettent en échec.
En vous inspirant de la formalisation du Sudoku, formalisez le problème des \(8\) reines à l'aide de la logique des prédicats.

Travaux pratiques

L'objectif de ces travaux pratiques est de réaliser un script qui lit une grille de Sudoku codée dans un fichier texte et tente de la compléter. Les indices dans la grille sont codés par les caractères 1 à 9 et les cases vides dont les valeurs sont à découvrir sont codées par le symbole point. Cliquez pour télécharger ce fichier exemple dans le répertoire où vous écrirez votre script.

Lecture de fichier. Découpage de chaîne. Ensembles Python

Lecture de fichier

Pour lire le contenu d'un fichier, il faut tout d'abord créer un fichier logique en l'associant à un fichier physique pour une lecture (read). C'est la fonction open qui réalise cette opération. Le nom du fichier et le mode d'accès à ce fichier (ici en lecture) sont codés par des chaînes de caractères. On récupère ensuite très facilement le contenu du fichier en créant la liste des chaînes de caractères constituées par chacune des lignes du fichier, grâce à la méthode readlines(), puis on ferme*En réalité, on indique au système que l'accès à ce fichier est de nouveau libre. le fichier avec la méthode close(). Testez le script ci-dessous qui demande à l'utilisateur le nom d'un fichier (saisissez le nom du fichier dans lequel vous aurez copié ce script par exemple), et renvoie la liste des chaînes de caractères correspondant aux lignes de votre fichier :

          def LireFichier(nom_du_fichier_physique):
          fichier_logique = open(nom_du_fichier_physique,"r")
          liste_des_lignes = fichier_logique.readlines()
          fichier_logique.close()
          return liste_des_lignes

          nomfichier = input("Fichier à lire ? ")
          lignes = LireFichier(nomfichier)
          print(lignes)
        

Testez ce script sur ce fichier qu'il faut enregistrer dans le même dossier. Le terminal va afficher

            ['une premiere ligne\n', 'une deuxieme ligne\n', 'et enfin une troisieme\n']       
          

Le dernier caractère de chaque chaîne de caractères de la liste est le caractère invisible retour charriot \n puisqu'il est présent à la fin de chaque ligne d'un fichier texte. On peut s'en débarrasser à l'aide de la méthode rstrip(), qui élimine tous les caractères de type espacement à la fin d'une chaîne de carac­tères. La boucle suivante

            for ligne in lignes:
            print(ligne.rstrip())
          

avec la liste lignes créée précédemment, affichera

          une premiere ligne
          une deuxieme ligne
          et enfin une troisieme
        

Découpage de chaîne

On peut découper une chaîne de caractères chaine suivant un chaîne séparatrice grâce à la méthode chaine.split(sep) qui renvoie la liste des sous-chaînes séparées par cette chaîne séparatrice. Par exemple, l'exécution des instructions

            chaine = "maths:en:folie"
            print(chaine.split(":"))
          

affiche la liste

            ["maths","en","folie"]
          

Sans paramètre, la chaîne séparatrice pour l'appel chaine.split() est le caractère d'espacement.

En combinant la lecture du fichier, le retrait du retour charriot, le découpage des chaînes et l'écriture en compréhension des listes, la fonction suivante a pour paramètre le nom d'un fichier contenant une grille de Sudoku et renvoie la liste des 9 listes contenant les 9 valeurs de la grille :

          def LireGrille(nom_fichier_grille):
          fichier_grille = open(nom_fichier_grille,"r")
          grille = [(ligne.rstrip()).split() for ligne in fichier_grille.readlines()]
          fichier_grille.close()
          return grille
        

La procédure suivante permet d'afficher une grille en mettant en évidence les 9 régions :

          def AfficherGrille(grille):
          for l in range(9):
          if (l > 0) and ((l% 3) == 0):
          print(" ------+-------+------")
          for c in range(9):
          if (c > 0) and ((c % 3)  == 0):
          print(" |", end="")
          print((grille[l][c]).rjust(2), end="")
          print()
        

Ensembles

La syntaxe des ensembles Python est la même qu'en mathématiques, {a,b} est la paire constituée de a et de b. Malheureusement l'initialisation d'un ensemble \(X\) à l'ensemble vide qui devrait s'écrire naturellement X = {} n'est pas possible car elle est déjà utilisée pour créer un dictionnaire vide, il faut écrire X = set().

On rajoute un élément x à un ensemble X à l'aide de l'appel à la méthode X.add(x). On retire un élément x d'un ensemble X à l'aide de l'appel à la méthode X.discard(x). Les opérations ensemblistes de réunion, d'intersection, de différence, de différence symétrique sont codées respectivement |, &, -, ^ en Python.

{a,c} | {a,b,d} est l'ensemble {a,b,c,d} et {a,c} & {a,b,d} est le singleton {a}.

En séance

Vérifiez que la procédure AfficherGrille(grille) affiche la grille fournie comme suit. NB. Elle affichera un . à la place du ? qui ne sert qu'à il­lus­trer la ques­tion 4.
            9 . . | . 7 . | 3 . .
            . 1 5 | . 2 . | . 4 6
            . . 8 | 6 . . | 2 5 .
            ------+-------+------
            4 6 ? | 1 8 2 | . . .
            . 7 9 | . . . | 8 3 .
            . . . | 9 3 7 | . 6 2
            ------+-------+------
            . 3 7 | . . 1 | 5 . .
            1 8 . | . 5 . | 6 9 .
            . . 4 | . 6 . | . . 3
En guise d'introduction à la manipulation des ensembles, on considère les ensembles suivants :
          cinema = {"Alice", "Benoît", "Claire", "David"}
          sport = {"Benoît", "Bob", "Claire", "Emma", "Farid"}
          musique = {"Alice", "Farid", "Tom", "Claire"}
        

Écrivez les expressions Python qui affichent :

  1. qui participe à au moins une activité ?
  2. qui participe à toutes les activités ?
  3. qui fait du sport mais pas de musique ?
  4. qui fait du sport ou de la musique, mais pas les deux ?
  5. qui fait exactement une activité ?

Pourquoi print((cinema ^ sport) ^ musique) ne répond pas à la question 5 ?

Écrivez une fonction Inconnues(grille) qui renvoie le tuple des coordonnées des cases de la grille passée en paramètre qui ne sont pas des indices.
Écrivez les deux fonctions LibreL(ligne) et LibreC(colonne) qui renvoient respectivement l'ensemble des valeurs encore libres sur la ligne et la colonne. Pour la grille de l'exemple à la ligne d'indice 3 et la colonne d'indice 2 (on numérote à partir de 0) marquée par un point d'interrogation, ces deux fonctions renvoient respectivement les ensembles {3,5,7,9} et {1,2,3,6}.
Écrivez une fonction LibreR(ligne, colonne) qui renvoie l'ensemble des valeurs encore libres dans la région qui contient la case en (ligne,colonne). Pour la même case de coordonnées (3,2) de la question précédente, la fonction renvoie l'ensemble {1,2,3,5,8}. Indication : pour pouvoir parcourir toutes les cases de cette région, partez des coordonnées de celle dans son angle supérieur gauche obtenues à l'aide de divisions euclidiennes.
Écrivez la fonction Libre(ligne, colonne), qui renvoie l'ensemble des valeurs encore libres dans la case de coordonnées (ligne,colonne) à l'aide des trois fonctions précédentes. Pour la grille de l'exemple et la case de coordonnées (3,2), la fonction renvoie l'ensemble \[{\color{#FF8}\{3\}}=\{3,5,7,9\}\cap\{1,2,3,6\}\cap\{1,2,3,5,8\}.\]
Écrivez une fonction MAJ(grille), qui met à jour toutes les cases de coordonnées (ligne,colonne) pour lesquelles la fonction Libre a renvoyé un singleton– signifiant qu'une seule valeur y est possible – en remplaçant la valeur inconnue par celle contenue dans ce singleton. La fonction devra renvoyer un booléen indiquant s'il y a eu ou non une ou des valeurs dévoilées dans la grille.

Compléments hors séance

Écrivez une fonction Completer(grille), qui utilise les fonctions précédentes pour tenter de compléter la grille de Sudoku passée en paramètre et qui recommence tant que de nouvelles valeurs sont dévoilées. Testez votre script sur l'exemple ci-dessus ainsi que celui donné dans le cours.
La procédure de complétion proposée jusqu’ici suppose qu’à chaque itération, au moins une nouvelle case peut être remplie de manière certaine, c’est-à-dire que l'ensemble de ses possibilités est réduit à un seul élément. Cependant, certaines grilles de Sudoku nécessitent d’envisager plusieurs hypothèses successives et de revenir en arrière en cas d’erreur :
          . 2 . | . 7 . | 3 . .
          . . . | . 3 8 | 9 1 .
          . . . | . 5 . | . . .
          ------+-------+------
          . . . | . . . | . . .
          . 3 4 | 5 6 . | . . .
          . . . | . . . | . . .
          ------+-------+------
          . 9 2 | . . . | . . .
          . . . | . 9 7 | 1 . .
          . . . | . . . | . . 3

Testez votre code sur le sudoku ci-dessus. Vérifiez que sur cette grille, pour chacune des cases encore indéterminées, l’ensemble des valeurs possibles contient au moins deux éléments. Expliquez comment l'on pourrait procéder pour poursuivre la résolution de cette grille.