La logique

1) Introduction

La logique est la science du raisonnement exacte. Et on ne peut concevoir de raisonnement exacte sans langage exacte ni règles de production exactes. Tout se passe comme si le raisonnement était un procédé mécanique exacte c'est à dire dont la production et la vérification peut être faite par une machine dans laquelle les rouages s'emboîteraient parfaitement sans aucun jeu, et en appliquant les principes de la mécanique classique. Le raisonnement pour être incontestable doit pouvoir s'effectuer mécaniquement comme un programme informatique ou une machine idéale classique. Les mathématiques contemporaines se fondent toujours à partir de la mécanique classique.

Néanmoins, même si nous considérons la nature du raisonnement comme étant mécanique, il existe une partie inexacte qu'est l'intuition et qui est la partie la plus intéressante de la logique. Elle se rapproche davantage d'une culture, d'un corpus idéologique ou d'une âme, que d'un procédé mécanique et n'est pas construite puisque c'est à nous de la construire, à l'observateur de s'en faire une.

Si le raisonnement exacte se conforme au fonctionnement d'une machine, il est moins évident que pour l'intuition il en soit de même. Tous deux naissent pourtant d'un même processus de développement holistique, qui tire l'essentiel de son information, dans la confrontation avec la réalité au cours de son développement. Alors, si on ne peut pas regrouper en un germe l'ensemble des informations définissant le raisonnement et l'intuition, on peut néanmoins regrouper en un germe, la description d'un processus de création, c'est à dire les seuls informations nécessaires pour le lancer, un processus très adaptatif, qui s'ajuste constamment aux forces changeantes internes et externes. Et qui tire de cette confrontation toute l'information nécéssaire pour sa constitution. Ce qui explique pourquoi on ne peut pas savoir à l'avance le résultat du processus holistique.

Une façon d'appréhender l'intuition et son évolution est de s'en imprégner et de l'exercer. C'est pourquoi nous discuterons beaucoup sur la façon de voir les objets comme autant de points de vue différents, comme autant de facettes d'un même objet, pour percevoir davantage l'évolution de notre entendement, comme si nous naissions. Bien sûr cela ne peut, et nous porterons une part de l'inconscient collectif, sans même le savoir et sans pouvoir nous en défaire par nous-même.

Le raisonnement pour être incontestable doit pouvoir s'effectuer mécaniquement comme un programme informatique ou une machine idéale, et nous décrirons ces procédés mécaniques en portant notre attention moins sur la construction des démonstrations dont la mise en cause sera laisser à la charge des contradicteurs, que sur la construction des objects mathématiques eux-mêmes qui portent davantage l'intuition. Nous décrirons les bases de la logique sans utiliser la notion d'ensemble infini ni celle de modèle mais par le commencement qu'est le langage et la programmation.

Si le raisonnement se conforme au fonctionnement d'une machine, les bases de celui-ci peuvent être décrites assez simplement. Et on commence par décrire la plus petite structure, le booléen, et par quoi il est contenu, le bit.

2) Les opérateurs booléens 

En mécanique classique, le bit est une mémoire possédant deux états possibles, exclusifs et exhaustifs. Il est représenté par une case contenant soit `0` soit `1`. Le bit représente le quanta d'information minimum qui possède une structuration de données la plus simple et, en dessous du quel, la structuration change nécessairement de forme et de nature.

On étudie le bit. On sépare la case de son contenu. L'une désigne une variable. L'autre désigne un booléen.

L'ensemble des booléens est `{0,1}`. Le `0` correspond au false. Et le `1` correspond au true.

La variable est un opérateur booléen d'arité zéro. Elle fait partie d'un langage d'opérateurs. C'est une mémoire qui peut à ce stade être considérée comme un bit. Et elle contient un booléen.

Puis il faut considérer les opérations logiques d'arité supérieur. Un opérateur booléen d'arité `n` est une application, prenant `n` booléens comme arguments, et retournant un booléen, c'est à dire une application de `{0,1}^n -> {0,1}`.

La structure de corps étant une structure sur laquelle on a beaucoup de connaissance, on commence par regarder comment munir cet ensemble `{0,1}` d'une structure de corps. Et il y a exactement deux façons de munir cet ensemble d'une structure de corps. Cela produit deux corps symétriques l'un de l'autre que l'on note selon un code couleur :

`C_2 = `Corps `"("+ , 0, - , **, 1, "/ )"`
`C_2``= `Corps `"("``+``,``0``,``-``,``**``,``1``,``"/"` `")"`

Les définitions des corps sont données en notation programmative où le premier argument désigne l'addition, le second argument désigne l'élément neutre de l'addition, le troisième argument désigne l'opposé `-x` et aussi la soustraction `x-y` comme étant égale à `x + (-y)`, le quatrième argument désigne la multiplication, le cinquième argument désigne l'élément neutre de la multiplication et le sixième argument désigne la division.

Les corps sur l'ensemble sous-jacent `{0,1}` sont construit en choisissant un éléments neutre pour l'opération `+` qui est soit `0` ou soit `1`. L'autre éléments est alors l'élément neutre de la multiplication.

On muni l'ensemble `{0,1}` de l'addition `+` avec `0` comme élément neutre, et de la multiplication `**` avec `1` comme élément neutre, pour former le corps `C_2`. L'addition `+` correspond au ou exclusif noté w. La soustraction correspond à l'addition. La multiplication `**` correspond au et. La division qui est restreinte à `C_2×C_2"*"` correspond à la multiplication et est notée par `"*"`|. Nous avons :

`C_2 = `Corps `"("+ , 0, + , **, 1, **_|")"`
`C_2 = `Corps `"("` w`, 0,` w`,` et`, 1,` et| `")"`
`x` `+1``=`` ¬``x`
`x``+``y = x` w `y`
`x``** ``y = x` et `y`

Symétriquement, dans le corps `C2`. L'addition `+` correspond à l'équivalence <=>. La multiplication `**` correspond au `"ou"`.

`C_2``= `Corps `"("``+``,``0``,``+``,``**``,``1``,``**_|``")"`
`C_2`` = `Corps `"("`<=>`,0,`<=>`,`ou`,1,`ou| `")"`

`x` `+ 1``=`` ¬``x`
`x``+``y =  x` <=> `y`
`x``**``y =  x` ou `y`

Ces deux corps sont symétriques l'un de l'autre. La négation `¬` est l'isomorphisme entre ces deux corps.

`¬0 =``0`
`¬1 =``1`
`¬(x + y) = ¬x` `+`` ¬y`
`¬(x ** y) = ¬x` `**``¬y`
`¬``0`` = 0`
`¬``1`` = 1`
`¬(x``+``y) = ¬x + ¬y`
`¬(x``**``y) = ¬x ** ¬y`

Pour un opérateur quelconque `"f"` défini par `(x,y,z,...)->"f"(x,y,z,...)` et pour un opérateur unaire inversible quelconque `"u"`, la conjugaison de `"f"` par `"u"` se note `"f"^"u"` et est l'opérateur `(x,y,z,...)->"u"("f"(u^-1(x),u^-1(y),u^-1(z),...))`. Tandis que la composition de `"u"` par `"f"` se note `"uf" = "u"@"f"`.

Lorsque `"u"` est la négation, alors `"f"^"u"` désigne l'opérateur dual de `"f"`, et `"uf"` désigne la négation de `"f"`.

L'isomorphisme entre les deux corps est la conjugaison par la négation :

`0^¬``=``0`
`1^¬``=``1`
`"+"^¬``=``"+"`
`"*"^¬``=``"*"`

Cet isomorphisme permet de définir les opérateurs duaux quelques soit leur arité.

3) Liste exhaustive des opérateurs booléens d'arité 0, 1 et 2

Il y a `2^(2^0)` opérateurs d'arité zéro. Soit `2` opérateurs d'arité zéro : `{`0`,`1`}`

Il y a `2^(2^1)` opérateurs unaires. Soit `4` opérateurs unaires : `{`0`, `id`, ¬, `1`}` dont voici les tables de vérités :

`x` 0`(x)` id`(x)` `¬x` 1`(x)`
0 0 0 1 1
1 0 1 0 1

Il y a `2^(2^2)` opérateurs binaires. Soit `16` opérateurs binaires :

`{ `=>`, `<=`, `<=>`, `et`, `ou`, `d`, `g`, `1`, "¬"`=>`, "¬"`<=`, "¬"`<=>`, "¬"`et`, "¬"`ou`, "¬"`d`, "¬"`g`, `0`}`

dont voici les tables de vérités. On peut les regrouper par couples d'opposés. La négation de l'équivalence `"¬"`<=> correspond au ou exclusif que l'on note simplement w. Le ou exclusif et l'équivalence peuvent aussi être notés par `"¬"`= et =.

`x` `y` `x` 0 `y` `x` et `y` `x "¬"`=> `y`  `x` g `y` `x "¬"`<= `y` `x` d `y` `x` w `y` `x` ou `y` 
0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 1 1 1 1
1 0 0 0 1 1 0 0 1 1
1 1 0 1 0 1 0 1 0 1


`x` `y` `x` 1 `y` `x "¬"`et `y` `x` => `y` `x "¬"`g `y` `x` <= `y`  `x "¬"`d `y` `x` <=> `y` `x "¬"`ou `y`
0 0 1 1 1 1 1 1 1 1
0 1 1 1 1 1 0 0 0 0
1 0 1 1 0 0 1 1 0 0
1 1 1 0 1 0 1 0 1 0

 

4) Nombre d'opérateurs d'arité 3, 4, 5 et 6

Il y a `2^(2^3)` opérateurs ternaires. Soit `256` opérateurs ternaires.

Il y a `2^(2^4)` opérateurs quaternaires. Soit `65 536` opérateurs quaternaires. Soit `65×10^3`. Soit `65 Kilo`

Il y a `2^(2^5)` opérateurs quinquénaires. Soit `4 294 967 296` opérateurs quinquénaires. Soit `4×10^9`. Soit `4 Giga`

Il y a `2^(2^6)` opérateurs sixténaire. Soit `18 446 744 073 709 551 616` opérateurs sixténaire. Soit `18×10^18`. Soit `18 000 000 Téra`

Les opérateurs sixténaires sont trops nombreux pour être passés en revue de façon exhaustive.

5) Le codage des opérateurs

Pour que le codage soit dense c'est à dire tel que toutes les configurations de bits soient utilisées, il faut que le nombre de valeurs possibles soit une puissance de deux. Ainsi une valeur appartenant à l'ensemble `{0, 1, 2, 3, ..., 2^n-1}` est mémorisée de façon dense sur `n` bits.

Le codage joue un rôle important pour permettre la programmations. Mais il est nécessaire de fixer une norme pour pouvoir toujours utiliser le même codage et réutiliser les mêmes algorithmes. Nous adoptons les deux règles de programmation suivantes :

  1. Dans une liste de termes, l'adresse des termes commence par zéro et s'incrémente pour accéder au terme suivant de la liste.
  2. La transmission d'une liste de termes s'effectue dans l'ordre des adresses des termes. Ainsi les termes d'adresse les plus petites dans la liste sont transmis en premiers.

Puis on représente une liste de `n` termes sur le papier en l'écrivant de gauche à droite. Le terme le plus à gauche est le premier terme de la liste et possède l'adresse zéro. Le terme le plus à droite est le dernier terme de la liste et possède l'adresse `n-1`.

Notation mathématique : `(a_0, a_1, a_2, a_3,..., a_(n-1))`
Notation mathématique abrégée : `a_0a_1a_2a_3...a_(n-1)`

L'endianess big-endian est une règle qui consiste à toujours transmettre en premier les termes les plus significatifs. Transmettre en premier un terme, signifie le placer en premier dans la liste, c'est à dire à l'adresse zéro de la liste. Et dire qu'un terme est le plus significatif, signifie qu'il constitue la contribution additive la plus importante dans le codage entier. La règle inverse, qu'est l'endianess little-endian, consiste à transmettre en premier les termes les moins significatifs. Les deux endianess engendrent un codage différents qui correspond à un ordre symétrique des `n`-uplet de booléens.

Ordre des `n`-uplets : Les `n`-uplets se mettent dans l'ordre en accordant un poids plus important à l'adresse la plus petite (big-endian) ou à l'adresse la plus grande (little-endian) :

 
Liste des
booléens
Liste des couples
de booléens
Liste des triplets
de booléens
Ordre big-endian
(0, 1)
(00, 01, 10, 11)
(000, 001, 010, 011, 100, 101, 110, 111)
Ordre little-endian
(0, 1)
(00, 10, 01, 11)
(000, 100, 010, 110, 001, 101, 011, 111)

Codage des `n`-uplets : Le codage transforme une liste de booléens `(x,y,z)` en un entier `c`. L'opération inverse qui est le décodage, transforme un entier `c` en une liste de booléens `(x,y,z)` qui est sa représentation en base `2` dans le sens de gauche à droite pour l'endianess big-endian ou dans l'autre sens pour l'endianess little-endian.

On note `c÷n` la division entière de `c` par `n`.
Et on note `c` mod `n` le reste de la division, c'est à dire `c` modulo `n` compris entre `0` et  `n-1`.

Endianess
Codage du couple `(x,y)`
Décodage de l'entier `c`
Little-endian
`c = x + 2y`
`(x,y) = (c` mod `2, (c` mod `4)÷2)`
Big-endian
`c = 2x + y`
`(x,y) = ((c` mod `4)÷2, c` mod `2)`

Endianess
Codage du triplet `(x,y,z)`
Décodage de l'entier `c`
Little-endian
`c = x + 2y + 4z`
`(x,y,z) = (c` mod `2, (c` mod `4)÷2, (c` mod `8)÷4)`
Big-endian
`c = 4x + 2y + z`
`(x,y,z) = ((c` mod `8)÷4, (c` mod `4)÷2, c` mod `2)`

Dans la suite de l'exposé, nous n'utiliserons que l'endianess big-endian pour l'ordre et le codage des `n`-uplets. On adopte la notation bloc`(n,c)` pour désigner un bloc de `n` bits contenant l'entier `c`. Nous avons `c∈{0, 1, 2, 3, ..., 2^n-1}`. Le bloc bloc`(n,c)` correspond à une liste de `n` booléens dont le codage vaut `c`. Dans l'exemple précédent bloc`(3,c) = (x,y,z)`. Cela représente la décomposition en base `2` sur `3` bits de l'entier `c`. Par exemple, considérons la liste de booléens (1,0,1). Cette liste possède le codage `2^2+2^0 = 5`. Donc nous pouvons écrire :

bloc`(3,5) = `(1,0,1)

code(1,0,1)` = 1"×"2^2 + 0"×"2^1 + 1"×"2^0`
code(1,0,1)` = 5`

D'une façon plus générale bloc`(n,c)` représente la décomposition en base `2` sur `n` bits de l'entier `c`. Nous avons :

bloc`(n,c) = (x_0, x_1, x_2, x_3, ..., x_(n-1))`

`x = (c` mod `2^n)÷2^(n-1)`
`x_1= (c` mod `2^(n-1) )÷2^(n-2)`
`x_2 =(c` mod `2^(n-2) )÷2^(n-3)`
`x_3 = (c` mod `2^(n-3) )÷2^(n-4)`

`x_i = (c` mod `2^(n-i))÷2^(n-i-1)`

`x_(n-2) = (c` mod `2^2)÷2^1`
`x_(n-1) = (c` mod `2^1)÷2^0`

`c = 2^(n-1)x_0 + 2^(n-2)x_1 + 2^(n-3)x_2 + ... + 2^(n-i-1)x_i + ... + 2^1x_(n-2) + 2^0x_(n-1)`

Les opérateurs booléens sont implémentés par leur table de vérités qui sont des tableaux de booléens. Ces tables de vérités sont mises sous forme de listes de vérités et sont codées en des entiers. Par exemple, considérons l'opérateur =>, sa table de vérité est :

`x` `y` `x` => `y`
0 0 1
0 1 1
1 0 0
1 1 1
=>` = `(1,1,0,1)
=>` = `13

Chaque ligne correspond à un monde où toutes les variables d'entré (`x` et `y`) sont connues. Il existe un ordre des variables qui est `(x, y)`. Et il y a 4 mondes possibles constitués par les valeurs possibles que peuvent prendre ces deux variables. Ces 4 mondes sont listés dans l'ordre big-endian :

`({x=`0`,y=`0`},{x=`0`,y=`1`},{x=`1`,y=`0`},{x=`1`,y=`1`})`
((0,0), (0,1), (1,0), (1,1))
(00, 01, 10, 11)
(0, 1, 2, 3)

La table de vérité est trancrite en une liste de vérité. Dans notre exemple la table de vérité de => est (1, 1, 0, 1). Elle regroupe le résultat de l'opérateur => pour chacun des mondes dans l'ordre (00, 01, 10, 11). Le code de l'opérateur => est le code de sa liste de vérité (1, 1, 0, 1) qui est égale à `1"×"2^3 + 1"×"2^2 + 0"×"2^1+ 1"×"2^0 = 13`.

Un opérateur `n`-aire va prendre en argument un `n`-uplet de booléens pour produire un booléen en résultat. L'opérateur se comporte comme une mémoire adressable, l'adresse qui lui et transmise est le `n`-uplet de booléens passés en argument, et ce qu'il retourne est le booléen mémorisé à cette adresse. Pour savoir plus précisement comment est défini cet adressage, on descend plus profondément dans la pile des protocoles, à un niveau de protocole plus bas. La mémoire de l'opérateur se présente comme un bloc de bits, une liste de bits numérotés de `0` à `2^n-1`. Ce numéro est l'adresse d'un bit et correspond à un `n`-uplet de booléens, le `n`-uplet qui doit être utilisé en arguments pour pouvoir accéder au bit en question.

Considérons un opérateur unaire p(.), un opérateur binaire ×(.,.) de syntaxe centrée, et un opérateur ternaire f(.,.,.). Leur liste de vérités s'obtiennent ainsi :

p`=` (p(0),  p(1))
×`=`(0×0,  0×1,  1×0,  1×1)
f`=`(f(0,0,0),  f(0,0,1),  f(0,1,0),  f(0,1,1),  f(1,0,0),  f(1,0,1),  f(1,1,0),  f(1,1,1))

Et ces listes de vérités se codent ainsi :

code(p)`=  2^1`p(0) + `2^0`p(1)
code(×)`= 2^3`(0×0) + `2^2`(0×1) + `2^1`(1×0) + `2^0`(1×1)
code(f)`= 2^7`f(0,0,0) + `2^6`f(0,0,1) + `2^5`f(0,1,0) + `2^4`f(0,1,1) +
                    + `2^3`f(1,0,0) + `2^2`f(1,0,1) + `2^1`f(1,1,0) + `2^0`f(1,1,1)

Le codage des opérateurs se fait séparément pour chaque arité. Un opérateur d'arité n occupe une mémoire de 2n bits. Il y a 22n opérateurs n-aire différents codés de 0 à 22n -1. Et le code de l'opérateur correspond à sa table de vérité.

On généralise en considérant des opérateurs opérant sur `n` arguments booléens pour produire `m` résultats booléens. L'opérateur booléen est dit d'arité `(n,m)`. Il correspond à une liste de `m` opérateurs d'arité `n`, ou bien à une liste de `2^n` `m`-uplets de booléens. Il y a donc deux façons de coder ces opérateurs, soit comme la concaténation des codages des `m` opérateurs, ou soit comme codage par bloc de `m` bits de la table de vérité. Par exemple, comme nous avons et`= `(0,0,0,1) et <=>`= `(1,0,0,1), l'opérateur défini par `"f"(x,y)->(x` et `y,  x` <=> `y)` est codé par :

(0,0,0,1,1,0,0,1)` = 2^4+2^3+2^0 = 25`

ou par :

((0,1), (0,0), (0,0), (1,1)) `=` (1,0,0,3) `= (2^2)^3 + 3(2^2)^0 = 67`
(0,1,0,0,0,0,1,1) `= 2^6+2^1+2^0 = 67`

Il convient de définir deux types distincts pour désigner ces deux codages. On parlera de liste de `m` opérateurs booléens d'arité `n` pour le premier codage, et on parlera d'opérateurs booléens d'arité `(n,m)` pour le second codage.

Un opérateur d'arité `n` est définie par une table de vérité occupant `2^n` bits. Une liste de `m` opérateurs d'arité `n`, ainsi qu'un opérateur d'arité `(n,m)`, est définie par une table de vérité occupant `m**2^n` bits.

Etant donné `n` variables booléennes, il existe `2^n` mondes possibles. On remarque que la liste des `2^n` mondes (dans l'ordre big-endian) défini un opérateur prenant en argument `n` bits et retournant en résultat un monde c'est à dire `n` bits et qui sont exactement de mêmes valeurs. Autrement dit cet opérateur est l'opérateur identité d'arité `(n,n)`. Cet opérateur possède un code qui est :

`n`
Identité d'arité `(n,n)`
Code
1
(0, 1)
`1`
2
(0, 1, 2, 3)
`4^2+2"*"4^1+3"×"4^0   =   27`
3
(0, 1, 2, 3, 4, 5, 6, 7)
`8^6+2"*"8^5+3"*"8^4+4"*"8^3+5"*"8^2+6"*"8^1+7"*"8^0   =   342391`
`n`
`(0, 1, 2, ..., m-1)`
avec  `m= 2^n`
`sum_(i=0)^(m-1)m^i(m-1-i)   =   (m^m-m^2+m-1)/(m-1)^2`

Le nombre d'opérateurs booléens d'arité `(n,n)` est égal à : `2^(2^n n)`

L'identité booléenne d'arité `(n,n)` possède comme code : `((2^n)^(2^n)-2^(2n)+2^n-1)/(2^n-1)^2`

7) Classification des opérateurs

On classe les opérateurs booléens selon leur code qui constituent leur table de vérité :

Codage
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Opérateur binaire
0 et `"¬"`=> g
`"¬"`<= d
w
ou `"¬"`ou <=> `"¬"`d <= `"¬"`g => `"¬"`et 1
Opérateur unaire
0 id
`"¬"` 1










 
Opérateur zéro-aire
0 1












 

On peut déjà écarter les opérateurs dégénérés qui ne tiennent pas compte de toutes leurs entrés et qui correspondent ainsi à des opérateurs d'arité inférieur. Il y a 10 opérateurs binaires non dégénérés :

`{`et`, "¬"`=>`, "¬"`<=`, `w`, `ou`, "¬"`ou`, `<=>`, `<=`, `=>`, "¬"`et`}`

Il y a deux opérateurs d'arité zéro que sont `0` et `1`. Puis à chaque fois que l'on incrémente l'arité, le nombre d'opérateurs distincts croît de façon doublement exponentielle. Mais en même temps on accroît le nombre de symétries qui constitue autant de possibilité de calculs intermédiaires. Pour un opérateur `n`-aire, il existe `n!` permutations possibles de ses entrés. Puis on considèrera les `n+1` symétries de négation que sont les négations de chaque entré prise individuellement et la négation du résultat.

Si on note par `"P(.,.)"` un opérateur booléen binaire quelconque, on peut définir formellement ces transformations symétriques.

La permutation `s` est définie par :

`s("P")(x,y) = "P"(y,x)`

La négation `n_1` est définie par :

`n_1("P")(x,y) = "P"(¬x,y)`

La négation `n_2` est définie par :

`n_2("P")(x,y) = "P"(x,¬y)`

La négation `n` est définie par :

`n("P")(x,y) = ¬"P"(x,y)`

Noter que ces transformations sont nilpotentes d'ordre 2 et commutatives entre-elles de part leur construction :

`s@s=id`    
`n@n=id` `s@n=n@s` `n_1@n_2=n_2@n_1`
`n_1@n_1=id` `s@n_1=n_1@s` `n@n_2=n_2@n`
`n_2@n_2=id` `s@n_2=n_2@s` `n@n_1=n_1@n`


On représente ces transformations symétriques sur le shéma suivant :


On en déduit les règles suivantes :

`id`
`n`
`n_1`
`n_2`
`n_1@n_2`
`n@n_1@n_2`
`s`
`"P"(x,y)`
`¬"P"(x,y)`
`"P"(¬x,y)`
`"P"(x,¬y)`
`"P"(¬x,¬y)`
`¬"P"(¬x,¬y)`
`"P"(y,x)`
et
`"¬"`et
`"¬"`<=
`"¬"`=>
`"¬"`ou
ou
et
`"¬"`=>
=>
`"¬"`ou
et
`"¬"`<=
<=
`"¬"`<=
`"¬"`<=
<=
et
`"¬"`ou
`"¬"`=>
=>
`"¬"`=>
w
<=>
<=>
<=>
w
<=>
w
ou
`"¬"`ou
=>
<=
`"¬"`et
et
ou
`"¬"`ou
ou
`"¬"`=>
`"¬"`<=
et
`"¬"`et
`"¬"`ou
<=>
w
w
w
<=>
w
<=>
<=
`"¬"`<=
`"¬"`et
ou
=>
`"¬"`=>
=>
=>
`"¬"`=>
ou
`"¬"`et
<=
`"¬"`<=
<=
`"¬"`et
et
<=
=>
ou
`"¬"`ou
`"¬"`et

On utilise le tableau comme suit :

Dans la première colonne, l'opérateur ou est transformé par `n_1` en l'opérateur figurant sur la même ligne mais dans la colonne `n_1` et qui est un =>, autrement dit `x` ou `y` est identique à `¬x` => `y`

De même l'opérateur `"¬"`<= est transformé par `n_1` en l'opérateur et, ce qui signifie que `x "¬"`<= `y` est identique à `¬x` et `y`

De même l'opérateur et est transformé par `n@n_1@n_2` en l'opérateur ou, ce qui signifie que `x` et `y` est identique à `¬(¬x` ou ` ¬y)`

De même l'opérateur w est transformé par `n` en l'opérateur <=>, ce qui signifie que `x` w `y` est identique à `¬(x`<=>`y)`

8) Décomposition polynomiale dans la structures de corps

Il existe deux façons possibles d'implémenter une structure de corps sur l'ensemble des booléens `{0,1}`, cela définie deux corps symétriques l'un de l'autre que l'on note selon un code couleur. Leur définition en notation programmative est :

`C_2 = `Corps `"( "`w`, 0,` w`,` et`, 1,` et|`" )"`
`C_2`` = `Corps ` "("`<=>`,0,`<=>`,`ou`,1,`ou| `")"`

Que l'on renomme conventionnellement par :

`C_2 = `Corps `"("+ , 0, + , **, 1, **_|")"`
`C_2``= `Corps ` "("``+``,``0``,``+``,``**``,``1``,``**_|``")"`

Le premier argument désigne l'addition, le second argument désigne l'élément neutre de l'addition, le troisième argument désigne la soustraction, le quatrième argument désigne la multiplication, le cinquième argument désigne l'élément neutre de la multiplication et le sixième argument désigne la division.

Noter alors que quelque soit les booléens `x` et `y`, nous avons :

`¬x   =   x + 1`
`x + y   =   x` w `y`
`x ** y   =   x` et `y`
`0``= 1`
`1``= 0`
`¬x  =  x` `+ 1`
`x``+``y =  x` <=> `y`
`x``**``y  =  x` ou `y`

On donne les définitions des 16 opérateurs binaires dans les deux corps qui se notent en notation classique par `(C2,+,**)` et `(C2,+,**)` :

Code
Opérateur
binaire
Définition
dans C2
Code
maxien
Code
minien
Définition
dans C2
Code
maxien
Code
minien
0000
0
`x` 0 `y`
0
0000
0
0000
0
`1`
0001
1
1000
8
0001
1
`x` et `y`
`xy`
1000
8
0001
1
`xy``+``x``+``y`
1110
14
0111
7
0010
2
`x "¬"`=> `y`
`xy``+``x`
1100
12
0101
5
`xy``+``y` `+ 1`
1011
11
1011
11
0011
3
`x` g `y`
`x`
0100
4
0100
4
`x`
0100
4
0100
4
0100
4
`x "¬"`<= `y`
`xy``+``y`
1010
10
0011
3
`xy``+``x` `+ 1`
1101
13
1101
13
0101
5
`x` d `y`
`y`
0010
2
0010
2
`y`
0010
2
0010
2
0110
6
`x` w `y`
`x``+``y`
0110
6
0110
6
`x``+``y` `+ 1`
0111
7
1110
14
0111
7
`x` ou `y` 
`xy``+``x``+``y`
1110
14
0111
7
`xy`
1000
8
0001
1
1000
8
`x "¬"`ou `y` 
`xy``+``x``+``y``+`1
1111
15
1111
15
`xy` `+ 1`
1001
9
1001
9
1001
9
`x` <=> `y`
`x``+``y``+`1
0111
7
1110
14
`x``+``y`
0110
6
0110
6
1010
10
`x "¬"`d `y`
`y``+``1`
0011
3
1010
10
`y` `+ 1`
0011
3
1010
10
1011
11
`x` <= `y`
`xy``+``y``+`1
1011
11
1011
11
`xy``+``x`
1100
12
0101
5
1100
12
`x "¬"`g `y`
`x``+`1
0101
5
1100
12
`x` `+ 1`
0101
5
1100
12
1101
13
`x` => `y`
`xy``+``x``+`1
1101
13
1101
13
`xy``+``y`
1010
10
0011
3
1110
14
`x "¬"`et `y`
`xy``+`1
1001
9
1001
9
`xy``+``x``+``y` `+ 1`
1111
15
1111
15
1111
15
`x` 1 `y`
1
0001
1
1000
8
`0`
0000
0
0000
0

La multiplication se note parfois par absence de symbôle. Il faut alors faire attention à bien distinguer la multiplication utilisée dans `C2` qui est l'opérateur `"*"`, de la multiplication utilisée dans `C2` qui est l'opérateur `"*"`.

Les pôlynomes à deux variables `x, y`, dans un corps de caractéristique 2, peuvent se mettent sous la forme :

`b_0"*"x"*"y + b_1"*"x + b_2"*"y + b_3"*"1`

Les mônomes sont rangées du degré le plus grand au degré le plus petit en respectant l'ordre des noms de variables `(x, y)`. Le n-uplet de booléens `(b_0, b_1, b_2, b_3)` ainsi défini s'appel le code maxien. Mais on peut choisir de ranger les monomes du degrés le plus petit au degrés le plus élevé tout en respectant l'ordre des noms de variables `(x, y)`. Les pôlynomes se mettent alors sous la forme :

`a_0"*"1 + a_1"*"x + a_2"*"y + a_3"*"x"*"y`

Et le n-uplet de booléens `(a_0, a_1, a_2, a_3)` ainsi défini s'appel le code minien. Le principe du code big-endian ne permet pas vraiment de trancher lequel des deux codes est le plus pertinents.

Chaque opérateur booléen correspond à un polynôme dans le corps `C2` et à un polynome dans le corps `C2`, et possède donc un code minien et maxien pour chacun des deux corps. Cela se généralise pour un opérateurs d'arité `n` en utilisant `n` variables.


Dominique Mabboux-Stromberg, 2015

Sujet :

La logique
Opérateurs booléens. Liste exhaustive des opérateurs booléens d'arité 0, 1 et 2. La logique booléenne. Nombre d'opérateurs d'arité 3,4,5,6. Codage des opérateurs booléens. L'adressage indirecte. Classification des opérateurs

Sujets liés :

Le langage d'opérateurs
Structure libre. Partage et complexité.Taille, niveau et complexité. Enumération. Composition d'opérateurs. Implémentation selon la logique polonaise. Implémentation récursive. Les axiomatiques d'opérateurs. L-taille, L-niveau et L-complexité.

Le langage propositionnel
Symétrie opérées par négation et permutation des arguments. Propriétés algèbriques des opérateurs. Axiomatique d'opérateurs. Nomenclature

L'univers et les mondes
Les univers. Le produit d'univers. Le codage des mondes. La satisfaction d'une formule dans un monde. Totologie, contradiction et cohérence. Les formes normales disjonctive et conjonctive. Les formes normales polynomiales.

Les règles de raisonnements
Les extensions intérieurs. La qualité. Le système axiomatique de Hilbert. La règle d'inférence dite du Modus Ponens. Les 3 shémats d'axiomes. La déduction naturelle. Les 9 règles d'inférences