Brevet FR2714745A1 — publié le 19950707

"Procédé de conception d'un réseau de neurones à partir d'un programme d'ordinateur écrit dans un langage procédural décrivant les étapes logiques de résolution d'un problème" DESCRIPTION Domaine technique La présente invention concemrne un procédé de conception d'un réseau de neurones à partir d'un programme d'ordinateur écrit dans un langage procédural décrivant les étapes logiques de résolution d'un problème. Etat de la technique antérieure Au début de l'informatique, les ordinateurs étaient programmes en branchant des câbles. Comme ils avait très peu de mémoire cela était possible. On a par la suite remplacé les câbles par des bits à positionner, puis on a remplacé les bits par un assembleur qui, bien qu'en correspondance directe avec le binaire est plus compréhensible. L'apparition de langages plus évolués du type Basic Fortran, Pascal, C a rendu l'ordinateur accessible à une population très élargie, non restreinte aux initiés. Ces langages ont rendu possible la mise au point d'une quantité d'algorithmes exacts pour résoudre une quantité de problèmes. Avec l'ntelligence Artificielle et les systèmes experts, se sont développés encore une nouvelle génération de langages (Prolog par exemple). Au lieu d'implanter un algorithme exact, ces langages permettent de déclarer une base de faits, ou de règles. Ces faits et règles sont ensuite combinés entre eux pour construire des déductions logiques essayant de résoudre un problème donné. Le grand enthousiasme pour l'intelligence Artificielle et les systèmes expert s'est aujourd'hui calmé, car on en a compris les limites. Un des problèmes principaux de l'intelligence Artificielle est le problème de l'ancrage des symboles. Si en Intelligence Artificielle on arrive bien à manipuler des symboles, par contre on n'arrive pas à mettre un symbole en correspondance avec le monde extérieur bruité vaste et flou. De par sa nature symbolique, l'lntelligence Artificielle arrive difficilement à prendre en compte des données continues, statistiques. Elle a très peu de capacité d'apprentissage et de généralisation et nécessite un grand temps de développement. Après 'l'ntelligence Artificielle, les réseaux de neurones artificiels sont devenus le mouvement en vogue dans la recherche en informatique. Les réseaux de neurones artificiels comblent exactement tous les défauts de l'Intelligence Artificielle. Ils peuvent traiter des données floues, bruitées et continues. Ils peuvent apprendre et généraliser ce qu'ils ont appris sur d'autres données non présentées durant l'apprentissage. Ils nécessitent peu d'efforts de mise au point, il n'est pas nécessaire de demander l'expertise d'un être humain expert. De plus, les réseaux de neurones sont propices à la parallélisation et permettent donc d'exploiter la puissance des ordinateurs parallèles actuels. Ils sont en outre tolérants aux pannes. Si un neurone ne marche plus, I'ensemble du réseau continue cependant à fournir un résultat ayant du sens. On peut comparer la situation actuelle dans laquelle se trouvent les scientifiques vis-à-vis des réseaux de neurones à la situation dans laquelle se trouvaient les gens au tout début de l'informatique, en face de leurs machines qu'ils programmaient avec des fils ou avec des bits correspondant aux fils. Actuellement pour construire un réseau, il faut connecter avec des câbles plusieurs neurones entre eux, le plus souvent en couches. Si cela ne marche pas, on modifie le nombre de couches ou éventuellement le nombre de neurones. Pour l'instant les scientifiques étudient principalement des réseaux avec un petit nombre de neurones, moins d'une cinquantaine. De la même façon, les informaticiens du début de l'informatique programmaient avec des fils des machines avec très peu de mémoire pouvant exécuter très peu d'instructions. Cependant la recherche est très active dans le domaine des ordinateurs neuronaux et des machines de I 000 neurones, voire 100 000, commencent à être disponibles. En outre, il n'est pas nécessaire d'avoir une machine dédiée aux réseaux de neurones pour simuler des gros réseaux. De par leur nature parallèle, de très gros réseaux peuvent être simulés sur des ordinateurs parallèles, ces derniers sont à un plus grand degré d'avancement que les ordinateurs neuronaux. Le problème qui se pose actuellement est de savoir comment on va pouvoir piloter de telles machines neuronales de façcon à exploiter toute leur puissance. Il paraît ridicule de se limiter à l'étude et la simulation de petits réseaux alors qu'il est d'ores et déjà possible d'en simuler des gros. La résolution de problèmes de taille importante nécessite évidemment la construction de réseaux de neurones de taille importante. De même qu'un petit programme résout des petits problèmes, un petit réseau résout aussi un petit problème. L'application massive des réseaux de neurones dans l'industrie passe par la mise au point d'un procédé permettant de concevoir des gros réseaux de neurones. Un premier pas a déjà été accompli en matière de pilotage d'ordinateurs neuronaux. Ce sont les procédés permettant de construire des réseaux de neurones de manière plus pratique qu'en connectant seulement des neurones entre eux, comme décrit dans l'article référencé [3] en fin de description. Ces procédés utilisent un langage de description de réseaux de neurones. Ces langages proposent de définir des réseaux de neurones "briques de base", puis ensuite d'assembler ces briques pour construire des réseaux de neurones plus complexes. Ces réseaux de neurones plus complexes peuvent à leur tour être assemblés, etc... Cette conception hiérarchique est très pratique. Seuls les petits réseaux de neurones "briques de base" sont appris, car l'apprentissage ne converge raisonnablement que s'il y a un petit nombre de neurones. Ces petits réseaux peuvent alors être combinés pour former un gros réseau apte à résoudre un problème complexe. Cependant la puissance de ces langages est limitée à la description d'architecture de réseau. Une architecture de réseau spécifie comment les neurones sont reliés entre eux. Le concepteur doit explicitement mentionner les connexions entre neurones ou entre groupes de neurones. Ces langages sont comparables au langage assembleur. De même qu'il y a une correspondance directe entre assembleur et code binaire, il y a une correspondance bijective entre un langage de description de réseaux et le réseau lui-même. Cette correspondance directe signifie que l'on peut facilement passer d'une représentation à l'autre et vice versa. Le langage assembleur a permis aux initiés de développer de plus grosses applications, mais il n'a pas permis la vulgarisation de l'outil informatique en dehors du cercle des informaticiens chevronnés et l'intervention massive de l'informatique dans l'industrie. Le langage assembleur ne permet pas non plus d'écrire facilement des gros logiciels comme ceux qui existent actuellement. Ce ne sont donc pas les langages de description de réseaux de neurones qui vont permettre d'utiliser et de diffuser massivement dans le monde scientifique et industriel la puissance calculatoire des réseaux de neurones. Ces langages ne permettront pas d'exploiter la puissance de calcul des ordinateurs neuronaux ou parallèles de demain. L'invention a donc pour objet de résoudre le problème technologique suivant: comment faire pour piloter une machine de I 000 000 de neurones pour lui faire comprendre ce qu'on attend d'elle, et lui faire exécuter ? Comment faire pour que la conception de gros réseaux de neurones devienne aussi souple et facile que la conception de programmes ordinaires utilisant un langage de programmation ? Ce qui au fond fait le succès d'un langage de programmation, c'est le fait que le programmeur n'a plus à se préoccuper de la machine. Il décrit le travail qu'il veut lui faire faire dans un langage logique qui s'est complètement abstrait de la machine. D'ailleurs, la majorité des programmeurs d'aujourd'hui n'ont qu'une idée très vague de la manière dont leurs programmes sont digérés par la machine: ce n'est pas du tout leur préoccupation. Le procédé de digestion en question s'appelle "compilateur". Si on transporte cela dans le domaine des réseaux de neurones, tout naturellement vient l'idée de l'invention, qui est de concevoir un réseau de neurones avec un langage de type langage de programmation qui s'est abstrait des réseaux de neurones, un langage o l'on ne parle plus de neurones. Ce langage décrit seulement sur un plan logique et fonctionnel le travail à faire. A charge à un compilateur neuronal de transcrire cette description logique en un réseau de neurones. On sait que n'importe quel chercheur en réseaux de neurones artificiels décrit les réseaux de neurones qu'il utilise à l'aide d'un langage de programmation. L'invention n'a pas pour objet de construire un réseau de neurones, mais de ne plus se préoccuper de neurones du tout. L'utilisateur écrit un programme Pascal comme s'il s'agissait d'un ordinateur ordinaire, le compilateur neuronal traduit le programme en un réseau de neurones qui va exécuter ce qui est décrit dans le programme. Ce qui rend les réseaux de neurones intéressants est l'apprentissage. Mais, il n'est pas possible de faire de l'apprentissage sur des gros réseaux. La seule façon de construire des gros réseaux puissants est de combiner des petits réseaux appris chacun séparément. Pour conserver l'attrait principal des neurones il faut donc que notre langage de programmation comporte une instruction en plus par rapport à un langage de programmation ordinaire, cette instruction permettant d'inclure dans le calcul des réseaux préappris. L'instruction en question ressemble à un simple appel de fonction. Le-résultat est un langage permettant de combiner entre eux des réseaux de neurones à un niveau logique. On ne parle plus ni de neurones, ni de connexions; on fait simplement référence aux réseaux de neurones préappris par leurs noms, exactement comme si ces réseaux préappris performaient une fonction arithmétique ordinaire. Finalement la solution du problème technologique posé consiste à décrire ce langage et, surtout, à trouver un compilateur qui puisse traduire ce langage vers un réseau de neurones. L'étape de définition du langage est conceptuellement simple. On choisit à titre d'exemple un langage de programmation connu, le Pascal auquel on rajoute l'instruction nécessaire à l'inclusion de réseaux de neurones qu'on appellera CALLGEN. L'étape de compilation est compliquée. Elle constitue le corps de l'invention. Un langage de programmation est un langage dont la syntaxe est très stricte, utilisé par l'être humain pour décrire un algorithme qui est une suite d'étapes de calculs qui permettent de résoudre un problème donné. Le langage Pascal est un exemple de langage de programmation qui est repris tout au long de la description pour fixer les idées. La préoccupation des gens qui travaillent sur la compilation est de transcrire une description d'un algorithme utilisant un certain langage de programmation en une suite d'instructions exécutables par un ordinateur cible, de telle façon que l'ordinateur cible puisse résoudre le problème correspondant à l'algorithme. Jusqu'à présent, les compilateurs ont été écrits pour des ordinateurs cibles classiques. Par ordinateurs classiques, on entend des ordinateurs comportant une mémoire et un microprocesseur exécutant les instructions stockées dans la mémoire de facçon séquentielle et déterministe, sur des données elles-mêmes stockées dans la mémoire. Il n'existe actuellement aucun compilateur de langage de programmation pour ordinateurs neuronaux, un ordinateur neuronal étant une machine dédiée à la simulation d'un réseau de neurones. Cette absence de compilateur neuronal s'explique pour deux raisons: - les réseaux de neurones ont toujours été considérés comme des machines qui apprennent toutes seules. Envisager les réseaux de neurones sous un angle autre que l'apprentissage représente un changement de paradigme. L'apprentissage permet à un réseau de résoudre des problèmes difficiles pour lesquels il n'existe pas d'algorithmes efficaces et ce, par des modifications successives de ses poids. La reconnaissance des formes est un exemple de problème difficile. Cette technique de modification de poids fait intervenir le hasard par l'intermédiaire d'un tirage de nombres aléatoires. Diamétralement à l'opposé, le procédé de compilation proposé génère automatiquement un réseau de neurones qui résout un problème pour lequel il existe un algorithme. L'association réseau de neurones/apprentissage est à ce point forte que la première réaction d'un chercheur en réseaux de neurones est de considérer le concept de compilation neuronale comme absurde; - les ordinateurs neuronaux qui existent actuellement ne comportent pas encore un très grand nombre de neurones. Or on verra plus loin que le compilateur neuronal est intéressant spécialement pour gérer des gros réseaux de neurones. Il existe des logiciels permettant de construire des réseaux de neurones de manière pratique, comme décrit dans l'article [3]. Ces logiciels utilisent un langage de description de réseaux de neurones et ce langage est compilé vers un réseau de neurones. En l'apparence, l'ensemble forme un compilateur de réseaux de neurones. La différence par rapport à un procédé de compilation neuronale est que les langages de description utilisés ne permettent pas de décrire un algonrithme. Leur puissance est limitée à la description d'architectures de réseaux. Une architecture de réseaux définit comment les neurones sont reliés entre eux. Le programmeur doit explicitement mentionner les connexions entre neurones ou entre groupes de neurones. Un tel langage n'est pas abstrait, il est près de la machine neuronale. Au contraire dans le langage Pascal utilisé pour la compilation neuronale, aucune référence n'est faite à l'architecture sous-jacente, le programmeur décrit seulement l'algorithme qui résout son problème, à charge au compilateur d'en déduire l'architecture qui permet de résoudre le problème. Il est connu de réaliser un procédé de compilation d'un réseau de neurones en utilisant un langage de description dans lequel: - on définit des petits réseaux à partir d'une description écrite dans ledit langage; - on "éduque" les petits réseaux en fonction des besoins, en utilisant une "boite noire" qui est une collection de couples d'exemples (ei, si,); - on combine alors les petits réseaux en un gros réseau à partir d'une description écrite dans ledit langage. La "boite noire" définie ci-dessus est telle que le réseau réussit tout seul à générer si à partir de ei. Pour résoudre le problème de calculer une fonction f dont on connaît la valeur en un point ei, si; on lui présente des points o la fonction n'est pas connue, en espérant que le réseau pourra calculer f. L'Intelligence Artificielle désigne des systèmes qui fonctionnent à partir d'une base de règles et un moteur d'inférence. Les règles comportent un prédicat à vérifier et une conclusion qui est vraie si le prédicat est vrai. La base de règles traduit un ensemble de connaissances concernant un domaine bien délimité et le moteur d'inférence combine les règles entre elles pour manipuler des symboles et faire des déductions logiques. Un courant de recherche essaie de combiner cette approche Intelligence Artificielle symbolique avec l'approche réseau de neurones, pour faire des systèmes hybrides. La motivation de ce courant est le fait que ces deux approches sont complémentaires. Les systèmes hybrides utilisent un procédé pour transférer les connaissances contenues dans une base de règles vers un réseau de neurones. Ce procédé est appelé compilateur de base de règles. Il prend en entrée une base de règles de l'Ilntelligence Artificielle, et génère en sortie un réseau de neurones qui simule l'action du moteur d'inférence sur la base de règles décrite dans les articles [5] et [1]. Dans ce cas, le langage compilé est le langage utilisé pour écrire la base de règles. Ce langage a une syntaxe pauvre. Un programme dans ce langage consiste en une suite de règles, chaque règle ayant un prédicat et une conclusion. Un tel langage ne permet pas de décrire de façon effective n'importe quel algorithme de résolution de problème comme doit permettre un langage de programmation. Il ne peut être considéré comme un langage de programmation. C'est un langage limité à la déclaration de base de règles. A l'inverse, il est possible de décrire une base de règles à partir d'un langage de programmation tel que Pascal. Ainsi la puissance d'un compilateur neuronal est supérieure à la puissance d'un compilateur de base de règles. Par ailleurs, un compilateur de base de règles génère les réseaux de façon assez simple, en traitant les règles une par une et en rajoutant les neurones correspondant au fur et à mesure. La compilation neuronale n'est au contraire pas évidente car il faut traduire toutes les structures de contrôle que supporte un langage de programmation tel que Pascal, en neurones. On commence à savoir faire des compilateurs pour des ordinateurs parallèles, comme cela est décrit dans l'article [4]. Un ordinateur parallèle comporte plusieurs microprocesseurs qui travaillent en même temps. Ces compilateurs sont encore au stade de la recherche. Ils ne marchent pas encore très bien en ce sens que le programmeur doit aider le compilateur en précisant quel microprocesseur va faire quoi ou en indiquant o vont être stockées les données. Or c'est précisément ce travail de bas niveau, près de la machine, qu'est sensé accomplir un compilateur efficace, pour libérer au maximum le programmeur d'avoir à se préoccuper des caractéristiques particulières de l'ordinateur sur lequel il travaille et d'avoir à gérer les communications entre les microprocesseurs, ainsi que la répartition de la charge de travail entre les microprocesseurs. La compilation parallèle se rapproche de la compilation neuronale en ce qu'un ordinateur neuronal est un ordinateur parallèle. Mais c'est un type d'ordinateur parallèle particulier. Un ordinateur neuronal est un ordinateur parallèle à grain fin dans lequel chaque microprocesseur exécute un petit travail, le travail d'un neurone. Il y a beaucoup de microprocesseurs, autant qu'il y a de neurones, et le volume des communications est gros, chaque neurone devant communiquer avec tous ses neurones voisins. Or la tendance actuelle des ordinateurs parallèles et des compilateurs pour ordinateurs parallèles est contraire, comme décrit dans l'article [4]. Les ordinateurs parallèles tendent a être à gros grain. Chaque microprocesseur est puissant, il y a peu de microprocesseurs et on cherche à minimiser les communications entre les processeurs car elles cotent plus cher en temps que les calculs des microprocesseurs. Ces ordinateurs parallèles ne sont rien moins que plusieurs ordinateurs classiques mis les uns à côté des autres et communiquant des données entre eux. Si on considère un compilateur neuronal comme un compilateur pour machine parallèle, ce compilateur diffère radicalement des compilateurs décrits dans l'article [4], tant par la nature du procédé que par la nature du produit. Ainsi, bien qu'apparentés de par la nature parallèle de leurs produits, les compilateurs parallèles et les compilateurs neuronaux ne partagent rien d'autre en commun. La présente invention a pour objet de proposer un procédé de conception d'un réseau de neurones à partir un programme d'ordinateur écrit dans un langage procédural décrivant les étapes logiques de résolution d'un problème. Exposé de l'invention La présente invention concemrne un procédé de conception d'un réseau de neurones à partir d'un programme d'ordinateur écrit dans un langage procédural qui décrit les étapes logiques de résolution d'un problème, caractérisé en ce qu'il comprend les étapes suivantes: 1/ Définition d'une cellule comportant * des premiers registres utilisés pour le développement de la cellule, * des seconds registres utilisés pour mémoriser des étiquettes (qui représentent les attributs d'une cellule totalement développée appelée neurone), * des connexions pondérées pour relier les cellules entre elles de façcon ordonnée et orientée; 2/ Définition d'un graphe "initial" de cellules formé de trois cellules, une cellule de lecture appelée cellule ancêtre et deux neurones pointeurs aptes à classer les neurones par rangée; 3/ Développement d'un graphe de cellules qui est un ensemble de cellules reliées entre elles avec des connexions pondérées orientées et ordonnées dont l'architecture finale décrit le programme; 4/ Construction de l'arbre syntaxique du programme écrit en langage procédural, cet arbre comportant des étiquettes (chaque étiquette correspondant à un mot du langage procédural); /Définition d'un ensemble de transformations locales de graphes de cellules appelées macro-opérateurs", les macro- opérateurs pouvant être munis d'un paramètre, un macro-opérateur étant la transposition de chaque mot du langage procédural; 6/ Décomposition des macro-opérateurs suivant un ensemble de petites transformations locales de graphes de cellules appelées "opérateurs cellulaires" qui, assemblées, forment un code cellulaire par application de tableaux et obtention de codes cellulaires relatif à chaque macro- opérateur; 7/Modification de l'arbre syntaxique de façon à associer à chaque étiquette de l'arbre syntaxique un macroopérateur muni ou non de paramètres par application d'un tableau; 8/ Décomposition des macro-opérateurs en un arbre d'opérateurs cellulaires; 9/ Réécriture de l'arbre syntaxique modifié en remplaçant chaque macro-opérateur par son code cellulaire et obtention du code cellulaire d'un réseau de neurones correspondant au programme écrit dans le langage procédural; / Décodage du code cellulaire qui consiste à appliquer les opérateurs du code cellulaire sur le graphe initial et obtention du réseau de neurones; Avantageusement le procédé de l'invention présente les caractéristiques suivantes: on utilise des neurones ayant des dynamiques particulières aptes à diriger les flux de données dans le réseau de neurones à partir des instructions du programme écrit dans le langage procédural dirigeant les flux de données. Dans la traduction d'un programme écrit dans un langage procédural le réseau compilé comporte: 1/ Un ensemble de couches formées par des neurones indépendants les uns des autres. Chaque couche contient les valeurs de toutes les variables à un instant donné (autant de neurones/couches que de variables déclarées dans le programme); 2/ Le réseau compilé comporte aussi un ensemble de sous- réseau de neurones. Chaque instruction est traduite en un sous-réseau de neurones. Pour la compilation du sous-réseau, les macro-opérateurs du sous-arbre syntaxique modifié de chaque instruction i génèrent une transformation de graphe qui transforme une cellule en un sous-réseau calculatoire SRi. Pour N instructions on a N + I couches Cl... Cn+1. Chaque instruction i est compilée en un sous-réseau de neurones SRi intercalé entre les couches Ci (qui contient les valeurs des variables avant la réalisation de lI'instruction i) et Ci+1 (qui contient les valeurs des variables après l'exécution de l'instruction i). Il y a connexion de la couche Ci au sous-réseau. Les neurones de Ci correspondant aux-variables lues par l'instruction i vers les neurones du sous- réseau font faire les calculs en utilisant directement ces valeurs. Il y a connexion du sous-réseau à Ci+1: connexion des neurones du sous réseau contenant les résultats des calculs vers les neurones de Ci+1 correspondant aux variables modifiées. Ces caractéristiques sont valables pour chaque couche pour tout le programme écrit dans le langage procédural. Dans la description de la mise au point systématique des macro-opérateurs de l'arbre syntaxique modifié, on a quatre sortes de macro- opérateurs: - un macro-opérateur apte à créer un invariant, c'est-à-dire qu'ils donnent des voisins à la cellule ancêtre; toute cellule connectée à un macro-opérateur est connectée aux mêmes cellules voisines dans le même ordre. Ces cellules voisines correspondant à cette caractéristique sont appelées invariant; - des macro-opérateurs qui créent un sous-réseau de neurones calculatoires, aptes à faire des calculs; les macro-opérateurs du sous-arbre syntaxique modifié de chaque instruction génèrent une transformation de graphe qui transforme une cellule en un sous-réseau calculatoire SRi; - des macro-opérateurs qui créent une couche de neurones Cl; les macro-opérateurs du sous-arbre syntaxique modifié de la partie déclaration de variables du programme écrit dans un langage procédural génèrent une transformation de graphe qui transforme une cellule vérifiant l'invariant en une couche initiale de neurones; - des macro-opérateurs qui combinent pour chaque niveau les deux types de couches précédentes Ci et SRi; les macro- opérateurs de l'arbre syntaxique modifié qui servent à séquencer les déclarations et instructions entre elles. Ils génèrent des transformations de graphe et/ou des mouvements de tête de lecture d'un arbre à l'autre aptes à combiner les réseaux SRi entre eux ainsi que les couches Ci. Avantageusement on utilise un macro-opérateur CALLGEN qui a la syntaxe suivante " : = CALLGEN ("nom-code", ,..., )", le résultat de l'appel étant une valeur rangée dans la variable " ", le nom "nom-code" indiquant le nom du code cellulaire que l'on veut développer, " d'inclure des réseaux de neurones "briques de base" préappris. On utilise un macro-opérateur # IF qui permet de tester une condition au moment de la compilation, la condition testée ayant toujours la même forme. On teste si la première dimension d'un tableau contient plus de une colonne. Cette instruction permet de paralléliser automatiquement un programme écrit avec une stratégie de résolution "diviser pour régner". Dans cette stratégie, un problème de taille n est divisé en deux sousproblèmes de taille n/2, puis en quatre sous-problèmes de taille n/4. On utilise toujours l'instruction # IF conjointement avec des fonctions appelées par CALLGEN qui enrichissent la structure de données tableau. On met en évidence un motif invariant qui est le contexte de réécriture. Si l'environnement contient n variables, la cellule a n+2 liens en entrée et 2 liens en sortie, le premier lien en entrée et en sortie pointant vers la cellule pointeur entrée et la cellule pointeur sortie, le deuxième lien en entrée pointant vers une cellule appelée cellule "start", le deuxième lien en sortie pointant vers une cellule appelée cellule "next" qui est ou bien un neurone (macro-opérateur du type "expression"), ou bien une cellule de lecture bloquée (macro- opérateur du type "modification de l'environnement"), la cellule "next" étant chargée de faire la liaison entre le graphe généré par le macro- opérateur et le reste du réseau de neurones en amont. Les structures de données tableau permettent la définition des tableaux, leur écriture et leur lecture. Le neurone pointeur est apte à représenter la structure de données tableau dans le graphe de cellule durant l'étape de décodage. Le procédé de traduction de l'invention s'applique à un langage qui est une combinaison d'un langage de programmation "procédurale" et d'un langage de description de réseau de neurones. Ce procédé est caractérisé en ce qu'il comporte une étape préliminaire de construction de codes cellulaires de réseaux de neurones, de façon à rendre l'accès à partir de ce langage à une bibliothèque de fonctions, qui est un ensemble de fonctions très utilisées et/ou simples, apte à être traduite par des réseaux de neurones optimisés en termes de nombre de neurones et de rapidité d'exécution. Avantageusement, la construction de codes cellulaires de réseaux de neurones comporte une étape d'apprentissage des poids des connexions des neurones des réseaux, de façon à calculer une fonction quand on ne connait pas la procédure calculatoire simple, mais en connaissant le résultat pour une base d'exemples particuliers. Avantageusement, le procédé préliminaire de construction des codes cellulaires comprend les étapes suivantes: - construction de codes cellulaires de réseaux de neurones dont l'architecture reflète les particularités du problème à résoudre et dont les poids ne sont pas ajustés; - décodage du code cellulaire pour construire le réseau de neurones; - apprentissage du réseau à partir de la base d'exemples du problème à résoudre de façon à modifier les poids du réseau et/ou l'architecture; - rétrocodage du réseau en fonction des modifications et obtention d'un code cellulaire modifié apte à coder le réseau de neurones modifié par l'apprentissage. Avantageusement on complète ce langage par combinaison avec une bibliothèque de fonctions permettant de faire de la parallélisation automatique de programme en langage procédural. Le procédé de l'invention est apte à traduire un programme écrit dans un langage de spécification (langage utilisé avantageusement dans l'invention) avec un algorithme "diviser pour régner" en un réseau de neurones aptes à exécuter en parallèle les calculs du programme utilisant une bibliothèque qui définit des codes cellulaires calculant des fonctions de tableaux. Si l'on définit un outil permettant de décomposer les opérateurs cellulaires (microcodage), on définit un ensemble de microtransformations locales de graphe de cellules appelées "microcodes" qui, assemblées, forment des opérateurs cellulaires de division et de modification locale de la topologie du graphe. On définit une extension des microcodes de façon à microcoder tous les opérateurs cellulaires. Le procédé d'écriture d'une procédure, permettant d'implanter le procédé de traduction d'un programme écrit dans un langage procédural, utilise de façon indépendante une base de règles de réécriture de l'arbre abstrait et une procédure appliquant ces règles. Pour cela trois fichiers sont nécessaires: - un qui comprend le code qui permet la réécriture d'arbres; - un qui comprend les règles de réécriture; - un qui contient les prédéfinitions qui sont des morceaux de code cellulaire définis séparément, chaque code cellulaire peut être exprimé sous forme d'une combinaison de ces prédéfinitions. Une telle présentation permet une réduction de la taille mémoire du code cellulaire généré par le procédé de traduction. Le procédé de décodage utilise le microcodage qui permet d'implanter de façon efficace ce procédé. En effet, l'implantation machine des opérateurs cellulaires nécessite une seule procédure de décodage alors que sinon, il faudrait décrire une procédure de décodage par opérateur. La liste des microcodes des opérateurs est définie séparément dans des fichiers indépendants de la procédure de décodage. Si l'on définit un outil permettant de décomposer les macro- opérateurs, o des opérateurs permettent d'implanter les macro- opérateurs en décomposant la transformation de graphe correspondante en une transformation de graphe plus petite, le procédé de l'invention est avantageusement caractérisé en ce que l'ensemble des opérateurs cellulaires comprend en outre: - un opérateur BLOC qui permet le blocage du développement de la cellule durant l'étape de décodage du code cellulaire; -un opérateur JUMP qui permet de décomposer un code cellulaire en plusieurs arbres, chaque arbre codant un réseau de neurones pour ensuite décomposer les différents réseaux de neurones de facçon hiérarchique et modulaire; - un opérateur SPLIT appliqué à une cellule donnée qui génère un nombre de cellules égal au cardinal du plus gros paquet de liens de la cellule auquel il est appliqué; - un ensemble d'opérateurs qui testent une condition portant sur l'état du registre ou de la connectivité de la cellule qui exécute un tel opérateur. Suivant le résultat d'une condition, la cellule place sa tête de lecture sur le sous-arbre gauche ou le sous-arbre droit Ainsi le procédé de compilation de l'invention transforme un programme écrit dans un langage procédural en un réseau de neurones. Le langage utilisé dans l'invention est un langage de spécification. Ce langage de programmation est un langage procédural (par exemple le Pascal) complété par de nouvelles instructions qui permettent d'inclure les possibilités offertes par le langage de description de réseau. Le langage de spécification permet de combiner une description d'ordre logique et une description des connexions des neurones. Pour la conception de réseaux de neurones à partir d'un langage procédural (langage qui utilise des fonctions et des procédures pour factoriser le programme, des variables et des instructions modifiant les variables langage C, Fortran), on a l'application suivante: association de chaque neurone à un processeur d'un ordinateur parallèle comportant au moins un processeur et gestion des communications entre neurones et obtention d'un compilateur neuronal qui génère des instructions pour un ordinateur parallèle. Le langage de programmation peut être complété avec l'instruction # IF pour la compilation parallèle de programmes écrits avec un algorithme "diviser pour régner". Le procédé de traduction de réseaux de neurones de l'invention définit une nouvelle solution pour concevoir des réseaux de neurones. On commence par définir de petits réseaux de neurones sur lesquels on applique un apprentissage, puis on compose ces réseaux de neurones en utilisant un programme classique écrit dans un langage tel que Pascal, qui utilise des variables, des instructions qui modifient ces variables et des procédures ou des fonctions qui peuvent être appelées plusieurs fois. Le langage de programmation doit être complété en utilisant une instruction appelée CALLGEN qui permet d'appliquer un réseau de neurones à des données et de récupérer les sorties. Un réseau de neurones est alors vu comme une simple fonction parmi d'autres fonctions. Ce premier mode de conception permet d'allier la puissance d'expression d'un langage de programmation avec la puissance de calcul des réseaux de neurones. Elle permet ainsi de construire de très gros réseaux de neurones. On peut aussi composer des réseaux de neurones qui n'ont pas été appris, mais qui peuvent calculer en parallèle une bibliothèque de fonctions simples et souvent utilisées. On construit ainsi des réseaux de neurones capables d'exécuter en parallèle des tâches complexes. Brève descriDption des dessins - Les figures 1A et 1 B illustre le procédé de l'invention; - la figure 2 illustre un mécanisme de réécriture d'arbre; - les figures 3 à 6 illustrent différents nouveaux opérateurs; - les figures 7 à 9 illustrent le principe du compilateur; -les figures 10 à 56 illustrent l'exécution de différents macro- opérateurs; -les figures 57 et 58 illustrent la lecture et l'écriture dans un tableau; -les figures 59 à 61 illustrent l'exécution de différents macro- opérateurs; -les figures 62 à 65 illustrent différents exemples de réalisation. Exposé détaillé de modes de réalisation On trouve à la fin de la présente description différents appendices comprenant un lexique, une bibliographie et différents compléments techniques, faisant partie intégrante de la description. Le terme technique pour désigner un traducteur d'un progamme en un réseau de neurones est "compilateur". Un compilateur désigne un outil logiciel capable à partir d'un programme écrit dans un langage de programmation, de générer des instructions exécutables par un ordinateur. A partir de ces instructions, l'ordinateur peut alors faire le travail décrit par le programme. Un réseau de neurones est un ensemble de neurones connectés entre eux. Chaque neurone effectue une opération très simple en fonction de paramètres internes et de signaux reçus par ses neurones voisins; le réseau dans son ensemble peut cependant calculer des fonctions complexes. On va tout d'abord mettre en évidence les principales caractéristiques du procédé de l'invention. Celui-ci est un un procédé de conception d'un réseau de neurones à partir d'un programme d'ordinateur écrit dans un langage procédural qui décrit les étapes logiques de résolution d'un problème comprenant les étapes suivantes, illustrées à la figure 1A: 1/ Définition (10) d'une cellule comportant * des premiers registres utilisés pour le développement de la cellule, * des seconds registres utilisés pour mémoriser des étiquettes (qui représentent les attributs d'une cellule totalement développée appelée neurone), * des connexions pondérées pour relier les cellules entre elles de façon ordonnée et orientée; 2/ Définition (11) d'un graphe "initial" de cellules formé de trois cellules, une cellule de lecture appelée cellule ancêtre et deux neurones pointeurs aptes à classer les neurones par rangée; 3/Développement (12) d'un graphe de cellules qui est un ensemble de cellules reliées entre elles avec des connexions pondérées orientées et ordonnées dont l'architecture finale décrit le programme; 4/ Construction (13) de l'arbre syntaxique du programme écrit en langage procédural, cet arbre comportant des étiquettes (chaque étiquette correspondant à un mot du langage procédural); / Définition (14) d'un ensemble de transformations locales de graphes de cellules appelées "macro-opérateurs", les macro-opérateurs pouvant être munis d'un paramètre, un macro-opérateur étant la transposition de chaque mot du langage procédural; 6/ Décomposition (15) des macro-opérateurs suivant un ensemble de petites transformations locales de graphes de cellules appelées "opérateurs cellulaires" qui, assemblées, forment un code cellulaire par application des tableaux donnés aux annexes C.6 et C.7 en fin de description et obtention de codes cellulaires relatif à chaque macro-opérateur; 7/ Modification (16) de l'arbre syntaxique de façon à associer à chaque étiquette de l'arbre syntaxique un macro-opérateur muni ou non de paramètres par application du tableau de l'annexe C. 11; 8/ Décomposition (17) des macro-opérateurs en un arbre d'opérateurs cellulaires; 9/ Réécriture (18) de l'arbre syntaxique modifié en remplaçant chaque macro-opérateur par son code cellulaire et obtention du code cellulaire d'un réseau de neurones correspondant au programme écrit dans le langage procédural; / Décodage (19) du code cellulaire qui consiste à appliquer les opérateurs du code cellulaire sur le graphe initial et obtention (20) du réseau de neurones; Le procédé de l'invention présente les caractéristiques suivantes: on utilise des neurones ayant des dynamiques particulières aptes à diriger les flux de données dans le réseau de neurones à partir des instructions du programme écrit dans le langage procédural dirigeant les flux de données. Dans la traduction d'un programme écrit dans un langage procédural, le réseau compilé comporte: 1/ Un ensemble de couches formées par des neurones indépendants les uns des autres. Chaque couche contient les valeurs de toutes les variables à un instant donné (autant de neurones/couches que de variables déclarées dans le programme). 2/ Un ensemble de sous-réseaux de neurones. Chaque instruction est traduite en un sous-réseau de neurones. Pour la compilation du sous-réseau, les macro-opérateurs du sous-arbre syntaxique modifié de chaque instruction génèrent une transformation de graphe qui transforme une cellule en un sous-réseau calculatoire SRi. Pour N instructions on a N + 1 couches Cl... Cn+1. Chaque instruction i est compilée en un sous-réseau de neurones SRi intercalé entre les couches Ci (qui contient les valeurs des variables avant la réalisation de l'instruction i) et Ci+1 (qui contient les valeurs des variables après l'exécution de l'instruction i). Il y a connexion de la couche Ci au sous-réseau. Les neurones de Ci correspondant aux variables lues par l'instruction i vers les neurones du sous- réseau font faire les calculs en utilisant directement ces valeurs. Il y a connexion du sous-réseau à Ci+1: connexion des neurones du sous réseau contenant les résultats des calculs vers les neurones de Ci+1 correspondant aux variables modifiées. Ces caractéristiques sont valables pour chaque couche pour tout le programme écrit dans le langage procédural. Dans la description de la mise au point systématique des macro-opérateurs de l'arbre syntaxique modifié, on a quatre sortes de macro- opérateurs: - un macro-opérateur appelé "PROGRAMM" apte à créer un invariant, c'est-à-dire qu'ils donnent des voisins à la cellule ancêtre; toute cellule connectée à un macro-opérateur est connectée aux mêmes cellules voisines dans le même ordre. Ces cellules voisines correspondant à cette caractéristique sont appelées invariant; - des macro-opérateurs qui créent un sous-réseau de neurones calculatoires, aptes à faire des calculs; les macro-opérateurs du sous-arbre syntaxique modifié de chaque instruction génèrent une transformation de graphe qui transforme une cellule en un sous-réseau calculatoire SRi; - des macro- opérateurs qui créent une couche de neurones C1; les macro-opérateurs du sous-arbre syntaxique modifié de la partie déclaration de variables du programme écrit dans un langage procédural génèrent une transformation de graphe qui transforme une cellule vérifiant l'invariant en une couche initiale de neurones; - des macro-opérateurs qui combinent pour chaque niveau les deux types de couches précédentes Ci et SRi; les macro-opérateurs de l'arbre syntaxique modifié qui servent à séquencer les déclarations et instructions entre elles, par exemple SEMICOL, CALL F, CALL P, macro-opérateur correspondant au "; ", ceux correspondant aux appels de fonction et/ou de procédure. Ils génèrent des transformations de graphe et/ou des mouvements de tête de lecture d'un arbre à l'autre aptes à combiner les réseaux SRi entre eux ainsi que les couches Ci. Les structures de données tableau permettent la définition des tableaux, leur écriture et leur lecture. Le neurone pointeur est apte à représenter la structure de données tableau dans le graphe de cellule durant l'étape de décodage. Le procédé de traduction de l'invention s'applique à un langage qui est une combinaison d'un langage de programmation "procédurale" et d'un langage de description de réseau de neurones. Ce procédé est caractérisé en ce qu'il comporte une étape préliminaire de construction de codes cellulaires de réseaux de neurones, de façcon à rendre l'accès à partir de ce langage à une bibliothèque de fonctions, qui est un ensemble de fonctions très utilisées et/ou simples, apte à être traduite par des réseaux de neurones optimisés en termes de nombre de neurones et de rapidité d'exécution. La construction de codes cellulaires de réseaux de neurones comporte une étape d'apprenftissage des poids des connexions des neurones des réseaux, de façon à calculer une fonction quand on ne connaît pas la procédure calculatoire simple, mais en connaissant le résultat pour une base d'exemples particuliers. Le procédé préliminaire de construction des codes cellulaires comprend les étapes suivantes: - construction de codes cellulaires de réseaux de neurones dont l'architecture reflète les particularité du problème à résoudre et dont les poids ne sont pas ajustés; - décodage du code cellulaire pour construire le réseau de neurones; - apprentissage du réseau à partir de la base d'exemples du problème à résoudre de façon à modifier les poids du réseau et/ou l'architecture; - rétrocodage du réseau en fonction des modifications et obtention d'un code cellulaire modifié apte à coder le réseau de neurones modifié par l'apprentissage. On complète ce langage par combinaison avec une bibliothèque de fonctions permettant de faire de la parallélisation automatique de programme en langage procédural. Le procédé de l'invention est apte à traduire un programme écrit dans un langage de spécification (langage utilisé avantageusement dans l'invention) avec un algorithme "diviser pour régner" en un réseau de neurones, en utilisant la bibliothèque de l'annexe C.8, qui définit des codes cellulaires calculant des fonctions de tableaux pour implanter un algorithme "diviser pour régner" de manière à obtenir un réseau de neurones aptes à exécuter en parallèle les instructions du programme procédural. Si l'on définit un outil permettant de décomposer les opérateurs cellulaires (microcodage), on définit un ensemble de microtransformations locales de graphe de cellules appelées "microcodes" qui, assemblées, forment des opérateurs cellulaires de division et de modification locale de la topologie du graphe. L'annexe C.2 décrit la syntaxe du microcodage et l'annexe C.3 liste les microcodes des opérateurs cellulaires de division et de modification locale du graphe. On définit une extension des microcodes de façon à microcoder tous les opérateurs cellulaires. Comme défini à l'annexe C.5, le procédé d'écriture d'une procédure, permettant d'implanter le procédé de traduction d'un programme écrit dans un langage procédural, utilise de façon indépendante une base de règles de réécriture de l'arbre abstrait et une procédure appliquant ces règles. Pour cela trois fichiers sont nécessaires: - un qui comprend le code qui permet la réécriture d'arbres; - un qui comprend les règles de réécriture; - un qui contient les prédéfinitions qui sont des morceaux de code cellulaire définis séparément, chaque code cellulaire peut être exprimé sous forme d'une combinaison de ces prédéfinitions. Une telle présentation permet une réduction de la taille mémoire du code cellulaire a générer par le procédé de traduction. Le procédé de décodage utilise le microcodage qui permet d'implanter de façon efficace ce procédé. En effet, I'implantation machine des opérateurs cellulaires nécessite une seule procédure de décodage alors que sinon, il faudrait décrire une procédure de décodage par opérateur. La liste des microcodes des opérateurs est définie séparément dans des fichiers indépendants de la procédure de décodage de l'annexe C.3. Si l'on définit un outil permettant de décomposer les macro- opérateurs, o des opérateurs permettent d'implanter les macro- opérateurs en décomposant la transformation de graphe correspondante en une transformation de graphe plus petite, le procédé de l'invention est avantageusement caractérisé en ce que l'ensemble des opérateurs cellulaires comprend en outre: - un opérateur BLOC qui permet le blocage du développement de la cellule durant l'étape de décodage du code cellulaire; - un opérateur JUMP qui permet de décomposer un code cellulaire en plusieurs arbres, chaque arbre codant un réseau de neurones pour ensuite décomposer les différents réseaux de neurones de façon hiérarchique et modulaire; - un opérateur SPLIT appliqué à une cellule donnée qui génère un nombre de cellules égal au cardinal du plus gros paquet de liens de la cellule auquel il est appliqué; - un ensemble d'opérateurs qui testent une condition portant sur l'état du registre ou de la connectivité de la cellule qui exécute un tel opérateur (voir annexe C.3). Suivant le résultat une d'une condition, la cellule place sa tête de lecture sur le sous-arbre gauche ou le sous-arbre droit. Ainsi le procédé de compilation de l'invention transforme un programme écrit dans un langage procédural en un réseau de neurones. Le langage utilisé dans rinvention est un langage de spécification. Ce langage de programmation est un langage procédural (par exemple le Pascal) complété par de nouvelles instructions qui permettent d'inclure les possibilités offertes par le langage de description de réseau. Le langage de spécification permet de combiner une description d'ordre logique et une description des connexions des neurones. Les étapes de compilation Le procédé de compilation de l'invention a été implanté. Le logiciel obtenu a pour but de prouver la validité de la compilation et de mesurer les performances du produit obtenu, c'est-àdire par exemple le nombre de neurones des réseaux compilés. Ce logiciel comprend différentes étapes montrées à la figure 1 B. L'entrée du compilateur est un programme écrit en langage Pascal "amélioré". Le produit est un réseau de neurones qui calcule ce qui est décrit par le programme Pascal. Le Pascal utilisé est dit "amélioré" parce qu'il propose des instructions supplémentaires par rapport au Pascal standard. Les étapes du procédé de traduction proposé sont: (a) la génération d'un l'arbre abstrait à partir du programme Pascal; (b) la réécriture de l'arbre abstrait en un code cellulaire à l'aide d'une grammaire d'arbre; (c) le décodage du code cellulaire en un réseau de neurones; (d) l'allocation et l'ordonnancement du réseau de neurones sur une machine physique. La première étape (a) est l'extraction de l'arbre syntaxique à partir du programme Pascal. C'est une technique standard utilisée comme première étape pour compiler n'importe quel langage de programmation. Cet arbre syntaxique n'a toutefois pas une forme habituelle. Dans l'appendice C.4 une grammaire décrit les arbres syntaxiques utilisés. La grammaire définie génère des expressions entre parenthèses qui sont interprétables en des arbres syntaxiques corrects. Un arbre syntaxique peut être celui d'un programme, celui d'une procédure ou celui d'une fonction. Le compilateur doit générer un ensemble d'arbres. Un arbre pour le programme principal et un arbre pour chaque fonction ou procédure. La représentation entre parenthèses utilisée ici est inhabituelle. On omet de mettre des parenthèses lorsqu'il y a un seul sous- arbre: on se contente de mettre un blanc. Lorsqu'il y a deux sous-arbres, on considère qu'il y a un tronc qui part à droite et une branche qui part à gauche. Seule la branche est mise entre parenthèses. Cette représentation spéciale permet de décrire les arbres syntaxiques avec une grammaire simple. Les lettres majuscules et les parenthèses sont des terminaux. Les non-terminaux sont écrits avec des lettres minuscules entre crochets. En fait l'arbre syntaxique utilisé est obtenu à partir d'un arbre syntaxique standard, en faisant une suite de modifications. L'appendice C.10 décrit les modifications apportées par rapport à un arbre syntaxique standard. La troisième étape (c) utilise le codage cellulaire. Le codage cellulaire est un codage de réseaux de neurones décrit dans un article [2]. Ce codage fait intervenir des cellules. Le décodage consiste en un développement d'un graphe de cellules. La troisième étape est précisément le décodage du code cellulaire obtenu. La deuxième étape (b) constitue le coeur du compilateur. Cette étape est une réécriture d'arbre. Réécrire signifie écrire différemment, c'est-à- dire remplacer une suite de lettres par une autre suite de lettres dans le cas simple de la réécriture de mots. Ainsi en partant d'un mot initial, on le réécrit en un autre mot, puis encore en un autre mot, ainsi de suite jusqu'au mot final. Une réécriture d'arbres consiste par exemple à remplacer un noeud d'un arbre par un sous-arbre. Le sous- arbre recollé doit indiquer o recoller les sous-arbres fils du noeud réécrit. La deuxième étape consiste donc à remplacer chaque noeud de l'arbre syntaxique par un sous-arbre étiqueté par des opérateurs cellulaires. Lorsque les opérateurs constituant ce sous-arbre sont exécutés par une cellule, ils font une transformation locale du graphe, en remplaçant la cellule initiale par plusieurs autres cellules, connectées aux voisines de la cellule initiale. Chaque noeud de l'arbre syntaxique peut donc être associé à une transformation locale d'un graphe de cellules. On associe à chaque noeud de l'arbre abstrait un macro-opérateur qui effectue cette transformation. Un macro-opérateur effectue une transformation plus importante que celle réalisée par un opérateur du code cellulaire. Dans la majorité des cas, un opérateur cellulaire crée au plus une cellule, ou modifie au plus un registre et est paramétré par au plus un seul entier. Il faut plusieurs opérateurs cellulaires pour coder un macro-opérateur. Cela justifie l'appellation macro-opérateur. L'exposé du procédé de compilation peut être fait sans faire référence au codage cellulaire. On se place au niveau des macro-opérateurs, ceux-ci étant implantés par des sous-arbres d'opérateurs cellulaires, décrits dans l'appendice C.7. La réécriture de l'arbre syntaxique consiste justement à remplacer chaque noeud de l'arbre syntaxique par le sous- arbre du code cellulaire qui implante le macro-opérateur associé au noeud. Dans sa version actuelle le logiciel obtenu produit un réseau de neurones, c'est-à-dire une représentation adaptée à un ordinateur neuronal comprenant plusieurs processeurs spécialisés dans la simulation de neurones. Ce réseau de neurones est actuellement simulé sur un ordinateur classique. La quatrième étape (d) consiste à allouer ce réseau sur l'architecture physique d'un ordinateur neuronal. Cette étape doit prendre en compte des considérations de taille mémoire, de communications entre microprocesseurs et de précision arithmétique de calculs. Si l'ordinateur neuronal est idéal, c'est-à-dire comporte un nombre de neurones infini, totalement connectés avec une précision de calcul égale à un ordinateur classique, cette quatrième étape est évidente pour un homme de métier. Réécriture d'arbre On présente maintenant une façon simplifiée de réécrire les arbres. Un arbre désigne une structure de données, une façon d'arranger des données entre elles. Un arbre est composé de noeuds et d'arêtes reliant ces noeuds. Ces arêtes ne doivent pas former un cycle. En d'autres termes, il n'est pas possible d'aller d'un noeud à un autre noeud de deux façcons différentes. Pour simplifier, on n'a, sur la figure 2, représenté que les arêtes. Un arbre comporte un noeud appelé racine: c'est le noeud qui se trouve le plus haut. Le fait de définir la racine permet d'orienter toutes les arêtes vers le bas. Un noeud donné est connecté à son noeud père audessus de lui et à ses noeuds fils en dessous de lui. Dans le cas d'unarbre binaire, chaque noeud a au plus deux noeuds fils, appelés fils gauche et fils droit Ces noeuds sont eux-mêmes la racine de deux sousarbres appelés sous-arbre gauche et sous-arbre droit. Les noeuds de l'arbre sont étiquetés par des symboles. Sur la figure 2B, on représente seulement une étiquette, l'étiquette A. Une règle de réécriture comprend un membre gauche et un membre droit. Le membre gauche est un symbole, et le membre droit est un arbre qui comporte deux étiquettes spéciales, G et D mis pour respectivement gauche et droit Lorsque l'on veut réécrire un arbre t en utilisant une règle r, on cherche un noeud de t étiqueté par le symbole membre gauche de r, on coupe le sous-arbre gauche et le sous-arbre droit de ce noeud et on les met de côté. Puis on remplace le noeud par le membre droit de la règle, on recolle alors le sous-arbre gauche partout o il y a le symbole G et le sous-arbre droit partout o il y a le symbole D. On voit que l'application successive de plusieurs règles de réécriture fait grossir l'arbre de plus en plus. La figure 2A illustre un exemple de règle de réécriture, la figure 2B un exemple d'application de la règle de réécriture. Les neurones utilisés Un neurone est caractérisé par le calcul qu'il fait à partir de ses entrées. Un neurone classique fait la somme des entrées pondérée par les poids des connexions, puis applique une fonction appelée sigmoide. On utilise plusieurs sigmoides différentes. Chacune a un numéro. Une cellule possède un registre sigmo dans lequel est rangé le numéro de la sigmoide du futur neurone. Les quatre sigmoides utilisées sont indiquées sur les figures 3A à 3D: identité: figure 3A; - marche d'escalier L (L comme left): figure 3B; marche d'escalier R (R comme right): figure 3C; - égalité à zéro: figure 3D. Par ailleurs, on utilise pour la compilation de programmes écrits en Pascal des neurones non classiques qui font le produit de leurs entrées (Pi- unit), ou le quotient d'une entrée par une autre entrée (Div-unit). On pourrait simuler la multiplication et la division avec des neurones classiques, cependant cela coûterait cher en neurones. Pour s'assurer qu'un neurone calculant une opération arithmétique à deux opérandes attende que les deux opérandes soient arrivées avant de calculer son activité, on utilise une dynamique particulière. Les neurones décident de calculer leur activation suivant trois trgles: - un neurone calcule son activité dès qu'il a reç,u les activités de ses voisins; - les neurones d'entrée sont initialisés avec le vecteur d'entrée; - un neurone envoie son activité à ses voisins en sortie, lorsqu'il est initialisé o s'il vient de calculer son activité. On n'utilise pas d'unités spéciales pour coder les seuils. A un instant donné tous les neurones qui peuvent calculer leur activité le font. Ainsi cette dynamique particulière (notée DO) est moitié parallèle, moitié séquentielle. Il n'y a pas besoin d'entités globales pour contrôler le flot d'activités. Deux autres dynamiques sont utilisées par le compilateur. La dynamique D2 est applicable sur un neurone ayant exactement deux entrées. Comme pour DO le neurone attend d'avoir reçu les deux opérandes avant de procéder au calcul. Si la première entrée est strictement positive, le neurone se comporte comme un 1o neurone DO, sinon le neurone est dit bloquant; il ne propage aucune activité. La dynamique D1 permet de bloquer un flux d'activité. Les neurones EAND, que l'on verra ci-dessous, utilisent cette dynamique. La dynamique D2 est la suivante: le neurone remet à jour son activité dès qu'il reçoit une activité de l'un de ces voisins. Cette dynamique est utilisée par les neurones AOR, utilisés pour récupérer une activité sur un seul fils à partir de plusieurs fils, lorsqu'on ne peut savoir à l'avance par quel fils l'activité va arriver. Microcodaóe On est intéressé par une implantation pratique des opérateurs cellulaires et du codage cellulaire. Dans le but de produire un code cellulaire plus compact avec le compilateur, on introduit beaucoup d'autres opérateurs de divisions, ainsi que des opérateurs qui modifient les registres des cellules, ou qui font des transformations locales de la topologie sans changer le nombre de cellules ou encore qui influent sur l'ordre d'exécution des opérateurs par les cellules. Chaque nouvel opérateur peut avoir un argument entier qui spécifie le plus souvent un numéro de lien, ou la valeur avec laquelle on modifie le registre, ou le numéro d'un arbre. L'usage d'arguments entiers favorise la représentation compacte. Pour être plus clair, on renomme les opérateurs avec des noms plus explicites qu'une seule lettre et on les a microcodé. Un microcode est composé de deux parties. La première partie spécifie la catégorie de l'opérateur. Elle utilise trois lettres majuscules. DIV indique une division de cellules; TOP une modification locale de topologie; CEL, SIT, LNK une modification d'un registre de respectivement une cellule, un site, un lien. Une cellule possède une suite ordonnée de sous-sites d'entrée et une suite ordonnée de sous-sites de sortie. EXE, BRA indiquent des opérateurs utilisés pour gérer l'ordre d'exécution. BRA teste une condition, suivant le résultat la tête de lecture est placée sur le sous-arbre gauche ou sur le sous-arbre droit. HOM indique une division en plus de deux fils. AFF indique des opérateurs utilisés seulement par le logiciel d'affichage de réseaux de neurones. Les -différents opérateurs sont listés à l'appendice C.3. La seconde partie du microcode est une opérande. Pour CEL, SIT, LNK, l'opérande est une lettre minuscule codant le nom du registre. S'il y a un signe arithmétique, l'opérateur applique l'opération arithmétique sur le contenu actuel du registre et sur l'argument, puis il place le résultat dans le registre. Sinon il se contente de charger le registre avec la valeur de l'argument Pour EXE, l'opérande est le nom particulier de l'ordre d'exécution codé sur une lettre minuscule. Pour BRA, l'opérande indique le type de condition à tester, codé sur une lettre minuscule. Pour DIV, I'opérande est une liste de segments, chaque segment est composé d'une lettre et éventuellement d'une liste de signes arithmétiques. Au début, tout opérateur de division crée deux cellules. La cellule "1" hérite des liens en entrées et la cellule "2" hérite des liens en sorties. La suite de segments est alors analysée dans l'ordre inverse pour déplacer ou dupliquer des suites de liens d'une cellule vers l'autre. La figure 4 donne un exemple d'une telle analyse. Il s'agit du microcodage de l'opérateur ADL 2 (ADd on Link), 2 est la valeur de l'argument. Cet opérateur intercale une cellule sur le lien numéro 2. Le microcode est: DIVm 2. (a) Avant la division ADL, (b) Division en eux fils, (c) le segment l"m>" est analysé, (d) le segment "s" est analysé, (e) le segment "m façon chez les cellules voisines. La figure 5 explique la différence légère entre "d" et "r". (a) Avant la division de cellule, la cellule qui se divise est étiqueté "b". Elle a un voisin en entrée étiqueté "a". (b) le lien en entrée est dupliqué en utilisant un segment du type "d". (c) le lien en entrée est dupliqué en utilisant un segment du type "r'. La seule différence est l'ordre des liens fait par la cellule "a" entre la cellule fille "1" et la cellule fille "2". La lettre "s" indique de connecter le site de sortie de la cellule fille numéro "1" au site d'entrée de la cellule fille numéro "2". Elle ne nécessite pas de signes arithmétiques. Les signes arithmétiques spécifient la suite de liens qui va être déplacée ou dupliquée, en utilisant l'argument de l'opérateur. ' ', '=' qui indiquent les liens plus petits, égaux ou supérieurs à l'argument. '*' indique tout les liens. 'ô et '$' indiquent le premier lien et le demrnier lien. 'A' indique qu'il faut considérer les liens de la cellule voisine reliée à travers le lien dont le numéro est l'argument. '' est utilisé lorsqu'il est nécessaire de compter les liens dans l'ordre décroissant. Si '_' est placé avant les trois lettres majuscules qui indiquent le type de l'opérateur, son interprétation est différente. Il indique alors qu'il faut échanger les rôles du site d'entrée et du site de sortie. '' est utilisé pour remplacer l'argument par la valeur du registre de lien. ' |' est utilisé pour remplacer l'argument par le nombre total de liens divisé par deux. * Un microcodage similaire est utilisé pour les opérateurs du type TOP qui modifient localement la topologie en coupant ou en réordonnant les liens. Dans ce cas, la cellule fille unique hérite des liens en sortie et l'analyse des segments indique des mouvements de liens du site d'entrée de la cellule mère vers le site d'entrée de la cellule fille. Dans l'appendice C.3, il y a aussi un grand nombre d'opérateurs utilisés seulement pour étiqueter les cellules. Pendant le développement du réseau de cellules les neurones gardent leur tête de lecture sur le code cellulaire, sur le demrnier opérateur lu. Ainsi on utilise des opérateurs qui ne servent à rien pour étiqueter les feuilles du code cellulaire. Cela permet de voir à l'écran quelle fonction chaque neurone réalise. Nouveaux opérateurs On décrit à présent quelques opérateurs cellulaires utilisés pour la compilation de programme Pascal. Ces opérateurs ne peuvent être décrits de fac,çon précise par leur microcode. On les explique donc séparément. L'opérateur BLOC permet de bloquer le développement d'une cellule. Une cellule qui lit BLOC attend que toutes ses cellules voisines en entrée soient devenues des neurones. Cet opérateur est souvent utilisé dans le compilateur pour éviter qu'on ne commence à développer trop tôt certains morceaux de code cellulaire. Le compilateur génère plusieurs codes cellulaires pour le programme principal et un par procédure ou fonction. Ces codes aussi appelés "arbre-grammaire" ont un numéro. L'opérateur JMP utilise un argument entier et sert à relier les différents arbres entre eux. L'argument indique un numéro d'arbre-grammaire. La cellule de lecture qui exécute l'opérateur JMP x doit positionner sa tête de lecture sur la racine de l'arbre-grammaire dont le numéro est x. On a besoin de répartir les liens d'entrée en paquets de liens pour pouvoir les traiter séparément. Chacun des sites d'entrée et de sortie est divisé en plusieurs sous-sites. La façon dont ces sous-sites sont gérés est assez technique. Les sous-sites sont codés grâce à un registre de liens booléen appelé "Begin-Sub-Site". Quand ce registre est à un, il indique qu'un nouveau sous-site commence à partir de ce lien. Par convention, le premier lien d'un site a son registre "Begin-Sub-Site" positionné sur 0. Pour coder la place d'un lien entre deux cellules, une connexion est représentée par deux éléments, chacun inséré dans deux listes chaînées. Chacun de ces éléments contient un registre "Begin-SubSite" différent. Car une connexion peut commencer un sous-site dans le site d'entrée sans pour autant commencer un sous-site dans le site de sortie. Chacun des sites d'entrée et de sortie possède un registre booléen "divisable". Lors d'une division de cellule, un lien peut être dupliqué, la règle suivante détermine la propagation du contenu du registre "Begin-Sub- Site" de chacun des deux éléments de connexion. Si le registre "divisable" du site auquel un élément de connexion est rattaché est à 1, le registre "BeginSub- Site" est dupliqué, sinon le registre "Begin-Sub-Site" est propagé dans l'élément de plus petit numéro, tandis que l'autre élément a son registre "Begin-Sub-Site" mis à 0. Cette règle signifie que si le registre "divisable" est à 0, il n'y a pas création de sous-sites, mais il y a conservation des anciens sous-sites, si le registre "divisable" est à 1, un sous-site se divise en deux sous-sites. La figure 6(a) et (b) donne un exemple de division de sous- sites: (a) avant une division parallèle de la cellule étiquetée PAR, (b) après la division parallèle, on voit qu'un sous-site a été créé chez le voisin, dont l'état du registre "divisable" du site d'entrée était positionné sur 1, (c) avant l'exécution de l'opérateur SPLIT, (d) résultat de l'opérateur SPLIT, (e) une étape intermédiaire. Un sous-site est représenté par un petit disque noir. D'autre part, il faut aussi mettre à jour les registres "Begin-Sub- Site" pour les éléments de connexion correspondant aux cellules nouvellement créées par une division en deux (microcode commençant par DIV) ou une modification de la liste des connexions (microcode commencçant par TOP). Tout d'abord, s'il y a division, les registres "divisable" de la cellule mère sont dupliques. On a vu précédemment que pour DIV et TOP, la liste des connexion est créée par la concaténation de plusieurs segments de connexions. Dans le cas o le registre "divisable" est à 1, des marques de début de sous-site sont insérées de faç,on à ce que chaque segment forme un sous-site. Dans le cas contraire, aucune marque de début de sous-site n'est insérée. La répartition en sous-sites n'a en fait un intérêt que par rapport à l'opérateur cellulaire SPLIT défini précédemment Cet opérateur a un comportement bien particulier dans le cas o il y a plusieurs sous-sites. La figure 6 (c), (d) et (e) montre l'exécution du SPLIT dans le cas o la cellule a deux sous-sites d'entrée. C'est la généralisation du cas un seul sous-site. Certains liens sont dupliqués de manière à ce que le nombre de liens n sur chaque sous- site soit identique, avant que la cellule ne se divise en n cellules, chaque cellule fille ayant autant de liens en entrée qu'il y a de soussites d'entrée. De même pour les liens en sortie. Les registres de site sont dupliqués chez les cellules filles créées. Dans le cas o le registre "divisable" est à 1, la cellule a autant de sous-sites qu'il y a de liens; dans le cas contraire il n'y a aucun soussite. Principe du compilateur La figure 7 montre un exemple simple de compilation. On obtient le résultat de la compilation du programme Pascal: var a, b, c: integer; begin a = a+b; c = c+b; b = a+c; end. Chaque ligne pointillée correspond à la compilation d'une instruction. Les neurones réalisent une simple addition de leurs entrées. Les poids sont à 1, la sigmoide est l'identité. La ligne 0 représente l'environnement initial. Il est composé de trois valeurs "a", "b", "c" contenues dans les neurones a1, b1 et c1. A la ligne 1, la valeur de "a" a changé. Elle est contenue dans un nouveau neurone a2 qui contient la somme de "a" et "b". Pour faire cette somme, le neurone a2 est connecté en entrée aux neurones a1 et b1. La valeur de "c" change à la ligne suivante, puis la valeur de "b". On voit que les deux premières instructions a = a+b; c = c+b peuvent s'exécuter en parallèle par les deux neurones a2 et c2. Sur cet exemple, chaque variable est représentée par deux neurones au cours du temps. Chaque variable V du programme Pascal contient une valeur. La variable est initialisée au début du programme, puis elle change suivant les affectations qui lui sont faites. A chaque variable V on fait correspondre autant de neurones qu'il y a de changements possibles de la valeur de V. Tous ces neurones représentent la variable V au cours du temps. A un instant donné du déroulement du programme, V a une certaine valeur v, celle-ci est contenue dans un des neurones qui représentent V. Ce neurone est connecté en entrée aux neurones contenant la valeur d'autres variables ayant servi à calculer v et il est connecté en sortie à des neurones qui utilisent la valeur v pour faire d'autres calculs. L'environnement, en compilation, désigne l'ensemble des variables accessibles en un point donné du programme. Avant l'exécution de chaque instruction, l'environnement est représenté par une rangée r de neurones. Il y a autant de neurones que de variables. Chacun des neurones contient la valeur de la variable qu'il représente à ce moment là. Une instruction modifie l'environnement et les valeurs de certaines variables. Une instruction se compile en un réseau de neurones intermédiaire calculatoire qui va calculer les valeurs modifiées, à partir des anciennes valeurs contenues dans la rangée r et va ranger ces nouvelles valeurs dans une nouvelle rangée de neurones r1. La figure 8 interprète l'exemple simple de compilation montré figure 7 comme un réseau de neurones comportant trois couches calculatoires intermédiaires. Elle illustre une organisation en couches du réseau compilé à partir du programme Pascal var a, b, c integer begin a = a+b; c = c+b; b = a+c; end. Ce réseau de neurones n'est pas le réseau de neurones compilé, mais une représentation du réseau qui met en évidence sa structure. Le réseau comprend trois couches calculatoires intercalées entre quatre rangées de neurones contenant les environnements intermédiaires. La première rangée de neurones a1, b1 et c1 contient les valeurs initiales des variables "a", "b" et "c". Chacune des trois couches calculatoires est composée d'un seul neurone. La première couche calculatoire est le neurone a2, la deuxième est le neurone c2 et la troisième le neurone b2. Sur cet exemple il n'est pas nécessaire d'introduire de nouveaux neurones pour contenir l'environnement intermédiaire. Ainsi l'environnement intermédiaire après la première instruction (ligne pointillée 1) est la répétition des neurones a2, b1 et c1. Ainsi la totalité du programme Pascal se compile en une suite o10 de rangées de neurones intercalées entre des couches de neurones intermédiaires, calculatoires. La figure 8 montre comment, en répétant les neurones des variables non modifiées, on obtient effectivement une organisation en couches sur un exemple simple de compilation. En se plaçant à une grosse granularité, la compilation du programme se décompose en la compilation de chaque instruction, qui se traduit par l'ajout d'une couche de neurones calculatoires intermédiaires pour chaque instruction et celui d'une rangée de neurones contenant l'environnement modifié par l'instruction. Ainsi la compilation peut être vue comme un processus de construction. On construit la rangée de neurones contenant l'environnement initial, à partir des déclarations de variables du programme Pascal. Puis on dépose des couches de neurones calculatoires successives en compilant le programme Pascal instruction par instruction. Cette idée de construction progressive du réseau de neurones compilé peut être appliquée avec une granularité plus fine qu'une instruction Pascal. Une instruction Pascal peut être décomposée en plusieurs mots du langage Pascal. Ces mots sont organisé suivant une structure d'arbre appelée arbre syntaxique, comme représenté sur la figure 9. Cette figure 9 illustre, en effet, rarbre syntaxique de l'instruction "a: = a+b". A gauche l'arbre syntaxique est étiqueté par les mots du programme Pascal, à droite les étiquettes comprennent deux parties: la première partie contient la nature du noeud et la deuxième partie contient un attribut précisant la fonction du noeud. Par exemple IDF-AFF indique que le noeud contient le nom d'une variable dans laquelle on va écrire. IDF-LECT indique le nom d'une variable dans laquelle on va lire. BIN-OP indique le nom d'un opérateur binaire comme l'addition. ASSIGN indique que l'on fait une affectation. Le sous-arbre gauche doit contenir le nom de la variable à modifier. Le sous-arbre droit contient le calcul de la nouvelle valeur. Pour les noeuds IDF-AFF et IDF-LECT l'attribut du noeud contient le nom de la variable à écrire ou à lire. Pour le noeud BIN-OP l'attribut contient le nom de l'opérateur binaire, le noeud ASSIGN n'a pas d'attribut. On peut associer à chaque mot du langage Pascal étiquetant l'arbre syntaxique une modification locale du réseau de neurone, de faç,on à ce que l'ensemble des petites modifications mises bout à bout résultent en l'ajout au réseau de neurones de la couche calculatoire correspondant à l'instruction. Ceci est mis en place en utilisant un formalisme à peu près identique au codage cellulaire. La couche de neurones est développée en plusieurs étapes intermédiaires, en utilisant le développement d'un graphe de cellules. L'idée de la méthode de compilation est d'associer chaque mot du langage Pascal à une modification effectuée sur un graphe de cellules. Les notions de cellules, de graphes de cellules, d'opérateurs cellulaires et de codes cellulaires sont décrites dans l'article [2] cité précédemment. On rappelle ici ces notions en les replaçant dans le cadre du compilateur. Une cellule est un noeud d'un graphe orienté, dont les connexions sont ordonnées, appelé graphe de cellules. Une cellule gère aussi un ensemble de registres intemrnes. Certains sont utilisés pendant le développement, d'autres déterminent les poids et seuils du réseau de neurones final. Parmi les registres utilisés pendant le développement, on distingue un registre particulier appelé "tête de lecture". Chaque cellule lit sur l'arbre syntaxique à une positon différente. La tête de lecture sert à repérer cette position. Lorsque les cellules perdent leur tête de lecture, elles deviennent des neurones. Les étiquettes de l'arbre syntaxique vont représenter des instructions pour le développement des cellules qui agissent localement sur la cellule ou sur les connexions de la cellule. De façon plus formelle, on verra par la suite que ces instructions peuvent se décomposer en une suite cd'opérateurs cellulaires définis dans le codage cellulaire. Elles sont donc appelées des macro-opérateurs. Pendant un pas de développement une cellule exécute le macro-opérateur référencé par l'étiquette qu'elle lit et déplace sa tête de lecture vers le bas, dans l'arbre syntaxique. Si l'on veut développer un réseau pour compiler l'instruction Pascal "a: = a+b", le développement de cette instruction entraîne la création de quatre cellules mais, à la fin du développement un seul neurone reste en place. Le développement commence avec une seule cellule appelée cellule ancêtre connectée aux neurones contenant l'environnement courant. Si l'on considère le réseau de départ indiqué sur la partie droite figure 10, au départ la tête de lecture de l'ancêtre est positionnée sur la racine de l'arbre syntaxique, comme le montre la flèche connectant les deux. Ces registres sont initialisés avec des valeurs par défaut. Au fur et à mesure que ces cellules exécutent les macro-opérateurs, elles donnent naissance à toutes les autres cellules. A la fin, les cellules perdent leur tête de lecture et deviennent des neurones. Quand il ne reste plus de cellules de lecture, on obtient le réseau de neurones. L'exemple suivant donne une première idée du processus de compilation. Il est important de ne pas oublier que dans les figures les connexions sortantes et rentrantes sont ordonnées. C'est la position de la connexion sur le cercle symbolisant le neurone qui code le numéro de la connexion. La figure 10 illustre le développement de la couche neuronale correspondant à l'instruction Pascal "a: = a+b", sur la moitié droite de cette figure. Le développement commence avec une cellule ancêtre étiquetée "1" connectée en entrée à trois neurones étiquetés "a", "b" et "c". Ces neurones contiennent respectivement les valeurs des variables "a", "b" et "c". A gauche se trouve l'arbre syntaxique de l'instruction Pascal. La flèche entre la cellule ancêtre et le symbole ASSIGN de l'arbre syntaxique représente la tête de lecture de la cellule ancêtre. Les connexions sortantes et rentrantes sont ordonnées. C'est la position de la flèche d'arrivée sur le cercle symbolisant la cellule qui code le numéro du lien. Par exemple, le lien vers "b" est le lien numéro 2. La figure 11 illustre l'exécution à l'étape I du macro-opérateur ASSIGN, lu par la cellule ancêtre "1" de la figure précédente. La cellule ancêtre "1" se divise en deux cellules filles "1" et "2". Les deux cellules filles héritent des liens en entrée de la mère. La fille "2" est connectée vers la fille "1". A présent la tête de lecture de la cellule "1" est dirigée sur le noeud IDF-AFF et celle de la cellule "2" est dirigée sur le noeud BIN-OP. La figure 12 illustre l'exécution à l'étape 2 du macro-opérateur IDF-AFF, lu par la cellule "1". La cellule "1" supprime son premier lien et déplace son quatrième lien pour le mettre en première place. Elle perd sa tête de lecture et devient neurone. La figure 13 illustre l'exécution à l'étape 3 du macro-opérateur BIN-OP, lu par la cellule "2". La cellule "2" se divise en trois cellules "2", "3" et "4". Les cellules "3" et "4" héritent des liens d'entrée de leur mère et sont connectées en sortie vers la cellule "2", tandis que "2" garde seulement son lien en sortie, perd sa tête de lecture et devient neurone. Le signe "+" à l'intérieur du cercle indique que le neurone "2" fait une simple addition de ses entrées. La figure 14 illustre l'exécution à l'étape 4 du macro-opérateur IDFLECT, lu par la cellule "4". La cellule "4" disparaît après avoir connecté son premier voisin en entrée avec son voisin en sortie. La figure 15 illustre l'exécution à l'étape 5 du macro-opérateur IDFLECT, lu par la cellule "3". La cellule "3" disparaît après avoir connecté son deuxième'voisin en entrée avec son voisin en sortie. Il ne reste plus de cellules de lecture. La compilation de l'instruction Pascal "a: = a+b" est terminée. La cellule ancêtre "1" est bien connectée à trois neurones contenant I'environnement modifié. Elle peut commencer à lire et à développer l'instruction suivante. On a montré sur l'exemple précédent que l'arbre syntaxique d'une instruction Pascal peut être interprété comme un arbre étiqueté avec des macro- opérateurs cellulaires. Lorsque ces macro-opérateurs sont exécutés par des cellules, ils permettent de développer une couche de neurones qui calcule ce qui est spécifié par l'instruction Pascal. Cette démarche peut être généralisée à tout le programme Pascal. L'ensemble du programme Pascal (ou d'un programme écrit dans n'importe quel langage) peut être représenté par un arbre syntaxique. La figure 16 représente l'arbre syntaxique du programme Pascal "program p; var a: integer; begin read (a); write (a); end". Les premiers noeuds de l'arbre syntaxique déclarent des variables. Ils vont créer la première couche de neurones contenant les valeurs par défaut de ces variables. Les noeuds suivants de l'arbre syntaxique correspondent aux instructions. Ils vont créer plusieurs sous-réseaux de neurones calculatoires, les uns à la suite des autres. Cet arbre syntaxique n'a pas une forme habituelle. Il contient les déclarations de variables et les étiquettes ne sont pas rangées dans l'ordre classique. Cet arbre a une forme particulière dans le but depouvoir implémenter facilement la compilation de réseaux de neurones. L'appendice contient une grammaire BNF décrivant la forme de ces arbres syntaxiques. Pratiquement, on obtient ces arbres syntaxiques à partir des arbres syntaxiques standard en faisant des rajouts et quelques modifications, décrites dans l'appendice C. 11. La figure 17 illustre le développement du réseau de neurones simulant le programme Pascal "program p; var a: integer; begin write (a); end". sur la moitié droite de cette figure. Le développement commence avec une cellule ancêtre étiquetée "1" et représentée par un cercle. La cellule ancêtre est connectée à la cellule pointeur entrée (rectangle étiqueté "input") et à la cellule pointeur sortie (rectangle étiqueté "output"). A gauche se trouve l'arbre syntaxique de l'instruction Pascal. La flèche entre la cellule ancêtre et le symbole PROGRAM de l'arbre syntaxique représente la tête de lecture de la cellule ancêtre. Si l'on considère le réseau de départ sur la moitié droite de la figure 17, les cellules pointeur d'entrée et pointeur de sortie (indiquées par des rectangles sur la figure) à laquelle est reliée la cellule ancêtre n'exécutent pas de macro-opérateurs. A la fin du développement, la cellule pointeur d'entrée pointe sur les neurones d'entrée du réseau et la cellule pointeur de sortie pointe sur les neurones de sortie du réseau. Comme pour le premier exemple, on constate que le graphe de cellules passe par des étapes intermédiaires o il atteint une taille de six cellules, à la fin il se réduit à deux neurones. La figure 18 illustre l'exécution à l'étape 1 du macro-opérateur PROGRAM. La cellule ancêtre donne naissance à deux autres cellules. Une cellule étiquetée "start et une autre étiquetée "next". La cellule start" est utilisée pour démarrer le réseau et pour gérer la propagation des activités. La cellule "next" n'a pas fini son développement Elle attend que toutes ses cellules voisines en entrée soient devenues des neurones (c'est-à-dire qu'elles aient perdu leur tête de lecture) pour continuer. La cellule ancêtre va alors lire le noeud étiqueté DECL. La figure 19 illustre l'exécution à l'étape 2 du macro-opérateur DECL. La cellule ancêtre donne naissance à une autre cellule étiquetée "var". Cette cellule représente la variable "a". Les connexions entrantes et sortantes de la cellule ancêtre sont à présent complètes et représentent une sorte d'invariant topologique vérifié avant la compilation neuronale de chaque instruction. Le premier lien entrant pointe vers la cellule "pointeur entrée". Le second lien entrant pointe vers la cellule "start". Les liens d'entrée suivants pointent vers les neurones représentant les variables de l'environnement. Le premier lien en sortie pointe vers la cellule "pointeur sortie", le deuxième lien en sortie pointe vers une cellule "next" qui sert à établir les connexions vers l'amont. La figure 20 illustre l'exécution à l'étape 3 du macro-opérateur TYPESIMPLE. Le macro-opérateur TYPE-SIMPLE a pour simple effet de positionner sur 0 (ligne pointillée) le poids reliant le neurone représentant la variable "a". Ceci n'est pas fait par le macro-opérateur DECL, car on ne peut pas savoir à l'avance si "a" ne sera pas de type compose. La figure 21 illustre l'exécution à l'étape 4 du macro-opérateur 1o SEMI-COL. Cet opérateur sert à séquencer deux instructions. La cellule "1" donne naissance à une autre cellule étiquetée "2". La cellule "1" va exécuter les macro-opérateurs correspondant à la première instruction "read a". Pendant ce temps, la cellule "2" est bloquée sur l'instruction d'après qui est "write a". La figure 22 illustre l'exécution à l'étape 5 du macro-opérateur READ. Un neurone "var" est créé. Il contient la nouvelle valeur de la variable a. Celui-ci contrairement au neurone "var" est relié à la cellule pointeur entrée. Cela signifie que la nouvelle valeur de a est rentrée de l'extérieur. La figure 23 illustre l'exécution à l'étape 6 du macro-opérateur IDF-AFF. Le neurone contenant l'ancienne valeur de a est éliminé car il ne sert à rien. La cellule "2" est débloquée, elle continue son développement. La figure 24 illustre le déblocage à l'étape 7 de la cellule "2". La cellule "2" récupère les liens en entrée de la cellule "1". La cellule "1" disparaît. On a restauré l'invariant. La compilation de l'instruction suivante peut commencer. La figure 25 illustre l'exécution à l'étape 8 du macro-opérateur WRITE. La cellule "2" donne naissance à une autre cellule "3" connectée à la cellule "pointeur sortie". Cette cellule "3" possède toutes les connexions d'entrée de la cellule "2" mère. On verra par la suite que pour inclure le cas o la variable à écrire est un tableau, on a besoin d'une cellule supplémentaire. La cellule "1" devient neurone. La figure 26 illustre l'exécution à l'étape 9 du macro-opérateur IDFLECT. La cellule "3" sélectionne l'entrée correspondant à la variable "a" pour la connecter à la cellule pointeur sortie. Puis la cellule "3" disparaît. La figure 27 illustre la demrnière cellule "bloc" qui se débloque et disparaît. Sa suppression entraîne la suppression en cascade de plusieurs autres neurones. Le réseau de neurones final comprend deux neurones d'entrée: la cellule "start" et la variable "a" et un neurone de sortie: la variable "a". Il lit "a" puis l'écrit, traduisant ce qui est spécifié dans le programme Pascal. Les transformateurs de graphes On a vu ci-dessus des petits exemples introductifs à la méthode de compilation. Celle-ci est basée sur la mise en correspondance des étiquettes de l'arbre abstrait avec des macroopérateurs cellulaires. On appelle chaque macro-opérateur du nom de l'étiquette qui lui correspond. Un macro- opérateur m remplace la cellule c qui l'exécute par un graphe d de cellules et de neurones. Ce graphe est rattaché au graphe global dans lequel se trouvait la cellule c par l'intermédiaire des cellules voisines de c. Le terme voisin désigne deux cellules connectées entre elles, directement ou par l'intermédiaire de neurones spéciaux appelés neurones pointeurs. Le graphe d doit indiquer quelles cellules vont exécuter les macro-opérateurs étiquetant les noeuds fils du noeud étiqueté par m. Comme ces cellules vont chacune lire un des noeuds fils du noeud étiqueté par m, et que chacun des noeuds fils est lu en général une et une seule fois, le nombre des cellules de lecture du membre droit est égal au nombre de sous-arbres. Il peut toutefois arriver que certaines cellules de lecture soient bloquées et finissent de traduire le macro- opérateur m plus tard (voir sur le lexique en fin de description le mot "blocage"). Dans ce cas le membre droit contient plus de cellules de lectures qu'il n'y a de sous-arbres. On distingue deux types de macro-opérateurs, les macro- opérateurs du type "expression", ils correspondent aux étiquettes générées à partir du nom terminal et produisent des neurones servant à calculer des valeurs, et les macro-opérateurs du type "modification de l'environnement" qui modifient l'environnement soit en l'augmentant soit en modifiant certaines de ses valeurs. On présente, à présent, tous les macro-opérateurs, ce qui définit entièrement le compilateur. On met en évidence un motif invariant qui est le contexte de réécriture. Le contexte de réécriture d'une cellule par un macro- opérateur est un invariant Si l'environnement contient n variables, la cellule a n+2 liens en entrée et 2 liens en sortie. Le premier lien en entrée et en sortie pointe vers la cellule pointeur entrée et la cellule pointeur sortie. Le deuxième lien en entrée pointe vers une cellule appelée cellule "start", le deuxième lien en sortie pointe vers une cellule appelée cellule "next" qui est ou bien un neurone (macroopérateur du type "expression'), ou bien une cellule de lecture bloquée (macro-opérateur du type "modification de l'environnement"). La cellule "next" est chargée de faire la liaison entre le graphe généré par le macro-opérateur et le reste du réseau de neurones en amont. Le premier macro-opérateur exécuté lors de l'exécution d'un programme est le macro-opérateur PROGRAM (figure 28). Ce macro-opérateur a pour but de créer le motif invariant. Par récurrence cet invariant est ensuite conservé, car pour chaque macro-opérateur m les cellules de lectures contenues dans son membre droit (destinées à exécuter d'autres opérateurs) ont leurs voisines qui vérifient le motif invariant. La figure 28 illustre l'exécution du macro-opérateur PROGRAM. Le but de ce macro-opérateur est de créer un motif invariant qui est conservé par les autres macro-opérateurs par la suite. La base de ce motif comprend une cellule ancêtre étiquetée "1" qui va développer un réseau de neurones sous l'effet des prochains macro-opérateurs, une cellule "start" servant à gérer la propagation des activités, une cellule "next" servant à connecter le réseau développé par la cellule "1" au reste du réseau de neurones en amont et les deux cellules pointeur entrée et pointeur sortie qui gèrent les entrées/sorties du programme. Pour associer un macro-opérateur à une étiquette de l'arbre abstrait, on respecte le motif invariant, on essaye de minimiser le nombre de neurones créés et on vérifie que l'effet du macro-opérateur est bien celui souhaité. Dans le cas d'un macro-opérateur du type "modification d'environnement", on s'assure que la modification est correcte; dans le cas d'un macro-opérateur type "expression", on s'assure que le sous-réseau généré calcule la bonne sous expression. De temps en temps on fait référence au code cellulaire défini dans l'article [2] cité précédemment. Dans l'implantation pratique, les macro- opérateurs sont décomposés en de plus petits opérateurs qui forment l'alphabet d'un code appelé code cellulaire. Pour chaque macro-opérateur, ces décompositions sont indiquées dans l'appendice situé en fin de description. Les opérateurs du code cellulaire réalisent des petites modifications de graphes. Par exemple, ils ne créent jamais plus de deux cellules et sont paramétrables par un seul entier. Les macro-opérateurs créent un grand nombre de cellules connectées de façon compliquée. La décomposition d'un macro-opérateur en opérateur est un moyen simple, efficace et rapide d'implanter les macro- opérateurs. Cela permet de résumer tous les macro-opérateurs en deux pages d'expression entre parenthèses, dans les appendices C.6 et C.7. Dans la compilation, il arrive fréquemment que certaines cellules, après exécution d'un macro-opérateur, bloquent leur développement jusqu'à ce que toutes leurs voisines soient des neurones, puis aillent exécuter un bout de code cellulaire pour effectuer une certaine transformation. Ces bouts de code correspondent à l'appendice C.6.3. On considère à présent les variables scalaires. On considère le cas des variables de type composé plus tard. Les macro-opérateurs DECL sont chaînés les uns à la suite des autres. L'effet de chacun de ces macroopérateurs est de rajouter un lien en entrée sur la cellule ancêtre, ce lien étant relié à une cellule elle-même reliée à la cellule "start", par un poids 0 (figures 29 et 30). Cette connexion assure que les neurones correspondants aux variables sont activés et peuvent faire démarrer le réseau. On suppose que toute variable est initialisée par défaut à 0. La figure 29 illustre l'exécution du macro-opérateur DECL. Ce macroopérateur complète le motif invariant en rajoutant une cellule étiquetée "var" qui va correspondre à une variable. La cellule "start" est connectée vers la cellule "var". Lors du démarrage du réseau la cellule "start" peut ainsi activer toutes les variables du réseau pour démarrer celui-ci. Dans cet exemple, seule une variable est déclarée. S'il y en a plusieurs il suffit d'appliquer pour chacune le même macro- opérateur qui vient greffer au réseau déjà existant la déclaration supplémentaire, faisant ainsi croître la taille du réseau par sa droite. La cellule "var" va lire des macro-opérateurs pour développer une structure permettant de représenter son type. La figure 30 illustre l'exécution du macro-opérateur TYPE- SIMPLE par la cellule "var" du graphe précédent On suppose que le noeud de l'arbre syntaxique de la figure précédente est une feuille étiquetée par ce macro- opérateur TYPE-SIMPLE. Ce macro-opérateur traduit le type d'une variable scalaire simple (booléen, entier ou réel). Il met à 0 le poids du lien reliant la cellule "start" vers la cellule stockant la valeur de la variable. Toute variable est initialisée à 0 par défaut. D'une façon générale, les poids connectant "start" aux variables valent toujours 0 de façon à ce que "start" propage bien l'influx nécessaire, sans toutefois modifier les activités. La cellule "var" perd sa tête de lecture et devient un neurone. La figure 31 illustre le motif invariant. On montre ici le graphe de cellules courant, après la déclaration de deux variables scalaires. On voit bien les deux neurones correspondants étiquetés "var". Ces neurones "var' avec les neurones "start' constituent la première couche du futur réseau de neurones. Ce graphe est choisi comme configuration initiale pour chacun des prochains macro- opérateurs décrits, pour éviter la répétition et bien montrer la propagation du même motif invariant représenté par cette configuration initiale. L'utilisation d'un motif invariant permet de décrire un compilateur pour tout langage procédural. L'exécution séquentielle repose sur une chaîne de cellules lectrices, associée à une liste d'instructions. La cellule de la chaîne à la position i lit le sous-arbre de instruction numéro i de la liste. La figure 32 illustre l'exécution du macro-opérateur SEMI-COL par la cellule ancêtre du motif invariant En (a) ce macro-opérateur crée deux cellules étiquetées 1 et 2. La cellule 2 doit être retardée jusqu'à ce que la cellule i ait terminé le développement du sous-réseau qui modifie les variables selon l'instruction contenue dans le sous-arbre syntaxique gauche. La cellule 2 est pour cela bloquée. La cellule 2 joue le rôle de la cellule "next" pour la cellule 1. Ainsi le motif invariant est bien vérifié pour la cellule 1. Elle attend que toutes ses voisines en entrée soient des neurones. A ce moment là, la première instruction a été traitée, la cellule 2 est débloquée. La situation est alors schématisée par (b). Avant de commencer à développer les instructions suivantes contenues dans le sous-arbre droit, la cellule 2 doit faire une transformation locale du graphe, de facçon à redevenir adjacente aux neurones "start" et "var" contenant l'environnement modifié. En (c), le motif invariant est restauré. La cellule 2 est prête à développer l'instruction suivante. Sur cette figure 32 les voisins d'entrée de la cellule 1 sont les neurones contenant l'environnement courant. La cellule à la position i+1 possède un seul voisin d'entrée à savoir la cellule i. La cellule en positon 2 doit être retardée jusqu'à ce que la cellule 1 ait terminé le développement du sous-réseau qui modifie les variables suivant instruction 1. Pour ce faire, elle bloque son développement jusqu'à ce que toutes ses cellules voisines en entrée soient devenues des neurones. La figure 33 illustre l'exécution du macro-opérateur ASSIGN par la cellule ancêtre du motif invariant. Ce macro-opérateur crée deux cellules étiquetées 1 et 2. La cellule 2 joue le rôle de la cellule "nex't" pour la cellule 1. La cellule I développe un sous-réseau calculant la valeur à affecter. La cellule 2 effectue les transformations du graphe nécessaires pour restaurer le motif invariant. Le motif invariant est perturbé car il y a un lien d'entrée en trop sur la cellule 2. L'affectation est l'exemple le plus simple d'instruction. Pour bien comprendre la figure 33 il faut se souvenir que chaque variable est repérée par son numéro de lien. Dans ces conditions, ranger une valeur dans l'environnement revient à connecter un neurone qui contient cette valeur à la cellule ancêtre qui traduit les instructions, ceci en vérifiant bien que le numéro de lien est le bon. Cette gestion de lien est effectuée par l'opérateur IFD-AFF de la figure 34. La figure 34 illustre l'exécution du macro-opérateur IDF-AFF par la cellule 2 du graphe précédent. Ce macro-opérateur est le premier exemple de macro-opérateur paramétré que l'on introduit Il est paramétré par le numéro de lien de la variable à affecter. Dans le cas présent cette variable s'appelle "a" et son numéro de lien est 2. Le macro-opérateur IDF-AFF 2 coupe le lien numéro 2 et déplace le dernier lien en deuxième place. C'est la traduction topologique de l'affectation. En coupant le lien numéro 2, on oublie l'ancienne valeur de "a". En déplac, çant le dernier lien connecté vers la cellule "1", en deuxième place, on assigne la nouvelle valeur "v" (en supposant que l'affectation est a: = v) qui va être calculée par le sous-réseau développée par la cellule 1. De la même façon pour pouvoir lire une variable, il suffit de connaître son numéro de lien et de connecter le neurone qui content la valeur vers le neurone qui a besoin de cette valeur. La figure 35 illustre l'exécution du macro-opérateur IDF-LEC par la cellule ancêtre du motif invariant. Ce macro-opérateur permet de lire le contenu d'une variable. Il est paramétré par le numéro de lien de la variable à lire. La valeur lue doit être envoyée vers le neurone "next". Elle peut être directement affectée, ou faire partie du calcul d'une expression. L'exécution de IDF-LEC 2 provoque la connexion du deuxième voisin en entrée vers le neurone "next" et la suppression de la cellule ancêtre. Les unités d'entrée du réseau correspondent aux valeurs écrites durant l'exécution du programme Pascal. Si dans le programme Pascal l'instruction "read a" apparaît, il y a un neurone d'entrée créé. En positionnant la valeur initiale de ce neurone à v, la valeur de a est initialisée à v. Les unités de sortie correspondent aux valeurs écrites durant l'exécution du programme Pascal. Si instruction "write a" apparaît il y a un neurone de sortie créé. A chaque fois que l'instruction "write a" est exécutée, la valeur de ce neurone est la valeur de a. Un neurone devient unité d'entrée s'il est connecté à la cellule pointeur entrée. Il devient unité de sortie s'il est connecté à la cellule pointeur sortie. Ainsi le macro-opérateur READ établit une connexion vers la cellule pointeur entrée, de même que l'opérateur WRITE établit une connexion vers la cellule pointeur sortie, comme représenté sur les figures 36 et 37. La figure 36 illustre l'exécution du macro-opérateur READ par la cellule ancêtre du motif invariant. Ce macro-opérateur est aussi paramétré par le numéro de lien de la variable "a" à interfacer, car il doit créer une structure de données représentant le type de la variable. Ici on traite le cas d'une variable scalaire. Le macro-opérateur crée un seul neurone "var". Ce neurone est relié à la cellule pointeur entrée. Il est donc un neurone d'entrée du réseau. Ainsi la variable "a" peut être initialisée de l'extérieur. La cellule ancêtre va ensuite exécuter un IDF-AFF, pour mettre à jour les liens et restaurer le motif invariant. La figure 37 illustre l'exécution du macro-opérateur WRITE par la cellule ancêtre du motif invariant. Trois cellules sont crées. La cellule 3 est un neurone chargé de passer l'environnement au neurone "next". La cellule 1 va développer un sous-réseau calculant l'expression à afficher. La cellule 2 est bloquée sur un code cellulaire SUPPRN-PN. Elle trouve son utilité dans le cas o l'expression n'est pas un scalaire comme on le verra par la suite. On représente ici son effet dans le cas scalaire. On voit que l'on peut se passer de la cellule 2 dans le cas scalaire. Les neurones contenant la valeur de l'expression calculée se trouvent reliés à la cellule pointeur sortie. La valeur peut ainsi être lue de l'extérieur. Les opérateurs binaires (voir figure 38) se compilent en développant un arbre de neurones implémentant chacun une opération arithmétique particulière grâce à une sigmoide adaptée. Les opérateurs unaires s'implémentent de la même façon que les opérateurs binaires. Seulement deux cellules sont créées au lieu de trois. L'une va développer le sous-réseau correspondant à la sous-expression à laquelle l'opérateur unaire est appliqué. L'autre va positionner sa tête de lecture sur le code cellulaire répondant au nom de l'opérateur unaire. La figure 38 illustre l'exécution du macro-opérateur BIN-OP par la cellule ancêtre du motif invariant. Ce macro-opérateur est paramétré par le nom de l'opérateur binaire. Trois cellules de lecture sont créées. Les deux premières vont chacune continuer de développer un sous-réseau de neurones pour calculer les deux sous-expressions. Ces deux cellules vérifient bien le motif invariant. La cellule 3 positionne sa tête de lecture sur le code cellulaire répondant au nom de l'opérateur. Ce code lui permet de régler ses poids et sa sigmoide de façon à implémenter l'opérateur binaire en question. Jusqu'à présent, les macro-opérateurs réécrivaient une cellule en 0, 1, 2 ou 3 cellules au maximum. Le macro-opérateur IF réécrit une cellule en un graphe dont la taille est proportionnelle à la taille de l'environnement. Cela représente un pas dans la complexité de la réécriture. Cette nouvelle classe de macro-opérateur peut être implémentée grâce à l'utilisation de plusieurs sous- sites et de l'opérateur SPLIT. La ligne Pascal "if a than b else c" peut se traduire par la formule booléenne (a AND b) OR ((NOTa) AND c) ou par la formule neuronale ((NOT a) EAND c) AOR (a EAND NOT b). Un booléen est codé sur + 1. Un NOT logique peut ainsi se réaliser avec un poids -1. Sur la figure 39, on voit une couche de six neurones EAND, divisée en deux sous-couches de trois. Ces sous-couches permettent d'aiguiller le flot d'activités vers le réseau calculant le corps du THEN, ou le réseau calculant le corps du ELSE. Les neurones EAND (Extended AND) ont une dynamique spéciale. C'est un AND réel qui a pour entrée un booléen et un réel. Si le booléen est faux, le neurone EAND ne sort ni 0, ni 1, mais rien. Si le booléen est brai, la sortie vaut le réel d'entrée. Ensuite un AOR (Arithmetic OR) récupère soit l'environnement de sortie du corps du THEN ou celui du corps du ELSE, pour le transmettre à l'instruction qui suit le "if then else". Les AORs ont aussi une dynamique spéciale. Ils remettent à jour leurs activités dès que l'une de leurs entrées a changé. La figure 39 illustre l'exécution des macro-opérateurs IF et THEN par la cellule ancêtre du motif invariant. Pour la clarté, on représente l'action combinée des deux macro-opérateurs IF et THEN. Il est facile de le redécomposer pour l'implémenter. Quatre cellules de lecture et une couche de six neurones EAND sont créées. La cellule 1 développe un sous- réseau permettant de calculer la valeur de la condition. Le booléen est codé sur + 1. L'opération logique NOR est réalisée à l'aide de poids -1 représentés en pointillé. Suivant la valeur de la condition, le flot d'activités représentant l'environnement courant est envoyé a droite ou à gauche. Ce sont les neurones EAND qui joue le rôle d'aiguillage. Un neurone EAND est passant si sa première entrée est à 1, sinon il est bloquant. Les cellules 2 et 3 développent respectivement le corps du THEN et le corps du ELSE. La dernière cellule est bloquée sur un code cellulaire X-AOR. Elle est destinée à créer une couche de neurones qui rassemble les lignes de sorties du THEN et du ELSE. La cellule 4 possède deux sous-sites d'entrée schématisés par deux petits disques noirs. La figure 40 illustre l'exécution du code cellulaire X-AOR par la cellule 4 de la figure précédente. La cellule 4 possède deux sites d'entrée représentés par deux disques noirs qui lui permettent de répartir ses liens d'entrée en deux listes. Le code cellulaire permet ensuite de traiter ses deux listes globalement. Le résultat est la production d'une couche de neurones AORs. Cette couche de neurones récupère soit l'environnement de sortie du corps du THEN ou celui du corps du ELSE pour le transmettre à l'instruction qui suit. Lorsque dans un calcul on a besoin d'une constante, celle-ci est stockée dans le biais d'un neurone dont la sigmoide est l'identité. Ce neurone est relié à la cellule "start", de façon à contrôler son activité, c'est-à-dire à quel moment et combien de fois il envoie la constante qu'il contient aux neurones qui en ont besoin. La figure 41 illustre l'exécution du macro-opérateur INT-CST par la cellule ancêtre du motif invariant. Ce macro-opérateur est paramétré par la valeur de la constante. INT-CST 3 a pour effet de positionner le biais de l'ancêtre à 3, de supprimer tous les liens excepté vers les neurones "start" et le neurone "next", de mettre le poids du lien vers le neurone "start" à 0, et la sigmoide de l'ancêtre à l'identité. Lorsque la constante est nécessaire le neurone "start" sert à activer le neurone I qui délivre alors la constante codée dans le biais. Le "while do " correspond à un réseau de neurones récurrent dans lequel une boucle infinie de calculs peut avoir lieu, tandis que l'architecture reste bornée, comme représenté sur la figure 42. Cette figure 42 illustre l'exécution du macro-opérateur WHILE par la cellule ancêtre du motif invariant. Trois cellules de lecture, trois neurones AOR, six neurones EAND, un neurone étiqueté 4 utilisé pour passer l'environnement sont créés. La couche de neurones AOR tampon sert de mémoire tampon pour stocker l'environnement entre deux passages dans la boudcle. La dynamique AOR est utilisée, parce que le flot d'activité arrive soit d'en haut (premier passage), soit d'en bas (passage suivant), mais jamais des deux en même temps. La cellule de lecture I développe un réseau qui calcule la condition du "while". La cellule 2 à gauche développe le corps du "while". Si la condition est vraie, le flot d'activité peut passer dans le corps de la boudcle, à gauche, car les trois EAND de gauche sont passants. Si la condition est fausse, ce sont les trois EAND de droite qui sont passants et le flot d'activité passe par la droite et sort de la boudcle. La cellule 3 développe une couche de neurones intermédiaires dans la boudcle, dont le rôle est de synchroniser le flot d'activités pour éviter des collisions. Aucune allocation mémoire ne se produit dans le corps de la boudcle. Le flot d'activité commence par passer dans une couche de neurones AOR qui sert de tampon. Il passe ensuite dans un réseau qui calcule la condition d'arrêt. Suivant la valeur de la condition, le flot d'activités sort de la boucle ou est envoyé dans le corps de la boudcle. Dans le dernier cas, il est réinjecté dans la couche de neurones tampon après avoir passé une couche de neurones synchronisatrice, comme illustré sur la figure 43. Cette figure 43 illustre l'exécution du code cellule X-SYNC par la cellule 3 de la figure précédente. La cellule 3 donne naissance à une couche detrois neurones plus un neurone "S" dont la dynamique est normale, intercalée entre la couche de neurones stockant l'environnement sortant du WHILE étiquetée ENV, et la couche de neurones AOR qui se trouve en entrée de boudcle. Le neurone "S" étant connecté en entrée à tout l'environnement ne devient actif que lorsque tout l'environnement est disponible. Le neurone "S" est relié à la couche de neurones normaux par des poids O, qui servent uniquement à bloquer le passage du flot tant que le neurone "S" n'est pas actif. Ainsi toutes les activités reboudclent en même temps et le flot est synchronisé. La synchronisation évite qu'un neurone donné du corps de la boucle ne remette à jour son activité deux fois, alors qu'un autre neurone ne le fasse aucune fois. Dans le cas de deux boudcles imbriquées, les neurones correspondant à la boucle interne reviennent à leur état initial lorsqu'ils ont terminé la boucle, et sont prêts à en exécuter une autre si la boucle externe l'exige. Le neurone "start' trouve son utilité principale dans le corps d'une boucle. Il est considéré comme une variable locale, il y a donc une copie de celui-ci dans la couche AOR tampon. Ce neurone est connecté à tous les neurones contenant des constantes utilisées dans le corps de la boucle. Il réactive ces neurones à chaque tour de boucle. Cela est indispensable au bon fonctionnement du réseau. La compilation du REPEAT est similaire à celle du WHILE. Le calcul de la condition se fait à la fin au lieu du début. On explique à présent comment les procédures et les fonctions se compilent à l'aide du programme Pascal "fil rouge" suivant qui nous servira à la fois pour préciser le passage des paramètres, I'appel ou l'exécution et le retour. progran procfunc Var glob:integer (*variable globale*) Procedure proc2(paf2:intoger) (*parametres formels *) var loc2:integer; (*variable locale a la proc edure proc2*) begin end; Procedure procl(pafl:integer) (*parametres formels *) var locl:integer; (*variable locale a la proc edure procl*) begin proc2(pef2); (*parametres affectifs a instancier *) end; (*passes par valeurs a proc2*) BEGIN (*corps programae principale) procl(pefl) (*parametres effectifs a instancler*) END. (*passes par valeurs a procl*) Dans toutes ces figures, le premier lien de sortie de la cellule 1 pointe vers la cellule pointeur sortie et le deduxième lien vers la cellule pointeur entrée. Si on représente l'inverse, comme c'est le cas ici, c'est seulement pour obtenir un graphe planaire plus lisible. On utilise un motif invariant légèrement modifié, comportant trois variables dans l'environnement. La première est une variable globale, la deuxième est un paramètre d'appel, la troisième est une variable déclarée localement dans la procédure appelée. Si l'on considère que le contexte o l'on se trouve à un certain point de l'arbre syntaxique du programme est l'instant d'appel à "proc2" dans "procl", l'environnement, du côté neuronique, comporte alors les variables globales, c'est-à-dire la cellule pointeur entrée, la cellule "start", la variable Pascal "glob", les variables qui sont locales à "procl", "pefl1" et "1oc1". Pour traduire l'appel de la procédure "proc2", on commence par retirer de l'environnement les variables locales à "procl". Ceci est fait par le macro-opérateur CALL-P représenté à la figure 44. Puis on développe les paramètres passés par valeur de "procl" à "proc2" (macro-opérateur COMMA représenté à la figure 46). Enfin la cellule ancêtre développe le corps de "proc2". Celui-ci commence par le macro-opérateur PROCEDURE qui insère une cellule chargée de dépiler les variables locales à "proc2", lorsque "proc2" rend la main (code cellulaire POP représenté à la figure 49). Apres cela, une cellule insérée par CALL-P exécute un code cellulaire RESTORE qui permet de restaurer les variables locales à "procl". Il n'est conceptuellement pas nécessaire de couper et de remettre les variables locales à "procl". Cependant, cela permet de pouvoir faire correspondre toujours le même numéro de lien à une variable donnée du programme. Les macro-opérateurs CALL-P, CALL-F et POP sont paramétrés par deux attributs. L'attribut GLOBAL est le nombre de variables globales de l'environnement L'attribut LOCAL est le nombre de variables locales. Le macro-opérateur CALL-F est plus simple que le CALL-P. Il n'y a pas besoin de créer de cellule pour restaurer l'environnement correct, car une fonction ne renvoie pas un environnement mais juste une valeur. Le macro- opérateur FUNCTION a un effet nul. En effet, pour la même raison que précédemment il n'est pas nécessaire de créer de cellule pour dépiler l'environnement Le macro-opérateur RETURN a aussi un effet nul. La figure 44 illustre ainsi l'exécution du macro-opérateur CALL- P par la cellule ancêtre du motif invariant à trois variables. Ce macroopérateur est paramétré par le nom de la procédure appelée. Trois cellules sont créées. La cellule 1 est chargée de développer plusieurs sous-réseaux de neurones, dont un sous-réseau pour calculer la valeur d de chaque paramètre d'appel. La cellule 2 va développer les instructions qui constituent le corps de la procédure appelée. Elle a sa tête de lecture sur la racine de l'arbre syntaxique de la procédure. On remarque que la cellule 2 n'est pas reliée aux neurones contenant les variables locales de la procédure appelante "pefl1" et "loc1". Ces variables ne sont en effet pas accessibles depuis "proc2". La cellule 3 est bloquée sur un code cellulaire RESTORE dont l'objet est de restaurer l'environnement de la procédure appelante, lorsque la procédure appelée est terminée. Pour ce faire, la cellule 3 garde des connexions vers les variables "pef1" et "loc1" locales à la procédure appelante. La figure 45 illustre l'exécution du code cellulaire RESTORE par la cellule 3 de la figure précédente. Lorsque la cellule 3 se débloque, le corps de la procédure "proc2" est développé. La cellule 3 est reliée à une cellule "next" elle-même reliée aux variables Pascal globales éventuellement modifiées par la procédure appelée. L'exécution de RESTORE remet ensemble les nouvelles variables globales et les anciennes variables locales de la procédure appelante. La figure 46 illustre l'exécution du macro-opérateur COMMA par la cellule ancêtre du motif invariant. Ce macro-opérateur crée deux cellules. La cellule 2 va développer un sous-réseau pour calculer la valeur d'un paramètre d'appel de procédure, la cellule 1 va continuer à développer les autres paramètres. La cellule "next" est celle qui va exécuter le corps de la procédure. La figure 47 illustre l'exécution du macro-opérateur NO-PARAM par la cellule ancêtre du motif invariant. Ce macro-opérateur permet simplement un retour en arrière. La cellule 1 de la figure précédente était partie pour développer un autre paramètre. Elle était arrivée, en fait, au bout de la liste des paramètres marquée par NO-PARAM. A ce moment là, la cellule I s'élimine. La figure 48 illustre l'exécution du macro-opérateur PROCEDURE par la cellule ancêtre du motif invariant. Ce macro-opérateur rajoute une cellule 2 intermédiaire bloquée sur un code cellulaire POP. Cette cellule se développe lorsque le corps de la boucle est développé. Son utilité est de couper les connexions vers les variables locales à la procédure appelée, de même que lorsqu'une sous-routine langage machine rend la main, elle dépile les variables locales. La cellule I n'a pas encore le neurone "loc2" dans son environnement, celui-ci est généré par les déclarations internes à la procédure appelée. La figure 49 illustre l'exécution du code cellulaire POP par la cellule 2 de la figure précédente. Cet opérateur permet de récupérer seulement la partie de l'environnement qui est globale. Les variables locales ne sont plus reliées au neurone 2 après son exécution. Ce macro-opérateur est équivalent à l'instruction "dépiler" en langage machine, utilisée pour le retour des sous- programmes. La figure 50 illustre l'exécution du macro-opérateur CALL-F par la cellule ancêtre du motif invariant L'environnement contient deux variables locales. Le macro-opérateur CALL-F a le même effet que CALL-P excepté qu'il ne crée pas la cellule 3 car il n'est pas nécessaire de restaurer l'environnement. La figure 51 illustre l'exécution du macro-opérateur RETURN par la cellule ancêtre du motif invariant. Ce macro-opérateur a un effet nul. Une des grandes richesses des langages de programmation est la structure de données tableau. Pour manipuler les tableaux, on utilise des neurones "pointeurs". Ce sont des neurones utilisés uniquement pour structurer des données, en arborescence. Ces neurones se trouvent aux noeuds de l'arborescence. Les données se trouvent aux feuilles. L'utilisation de neurones pointeurs assure que la cellule ancêtre possède un lien d'entrée par variable de l'environnement. Cela permet de traiter les variables séparément lorsqu'on veut lire ou écrire. On peut ainsi représenter des tableaux Pascal à plusieurs dimensions, ou des structures (mot clé Pascal "record"). La figure 52 montre un exemple de motif invariant étendu comportant un tableau 1D de deux éléments. La figure 53 utilise un arbre de profondeur deux, pour représenter un tableau à deux dimensions. Un arbre de profondeur d peut représenter un tableau à d dimensions. L'utilisation de plusieurs couches de neurones pointeurs pour stocker un tableau à plusieurs dimensions est nécessaire si l'on veut pouvoir manipuler les colonnes suivant chaque dimension. La figure 52 illustre un motif invariant étendu. L'environnement contient une variable scalaire et un tableau à deux éléments. La figure 53 illustre la représentation d'un tableau à deux dimensions à l'aide d'un arbre de neurones pointeurs PN de profondeur 2. La couche de neurones marquée "D" contient les données du tableau. C'est lors de la déclaration d'une variable tableau que cette structure d'arbre de neurones pointeurs est créée. On code le type d'une variable par une chaîne de macro-opérateurs TYPE-ARRAY (voir figure 54). Chacun de ces macro-opérateurs est paramétré par le nombre de colonnes existant dans la dimension qu'il représente. Cette chaîne se termine par un macro-opérateur TYPE-SIMPLE dont on a déjà vu l'effet à la figure 30. La figure 54 illustre l'exécution du macro-opérateur TYPE- ARRAY. Ce micro-opérateur permet de développer la structure de neurones pointeurs nécessaire pour coder un tableau. Il faut d opérateurs de ce type pour coder un tableau de d dimensions. Ce macro-opérateur est paramétré par un entier qui indique le nombre de colonnes de la dimension courante. C'est le seul exemple de macro-opérateur pour lequel plusieurs cellules vont lire le même noeud de l'arbre syntaxique. Beaucoup de macro-opérateurs doivent gérer les neurones * pointeurs à l'aide d'une exploration récursive de l'arbre des neurones pointeurs. Par exemple le IF, le WHILE, le X-AOR, le X-SYNC. Ce sont des opérateurs qui reconstruisent tous les neurones contenant l'environnement courant. La figure 55 représente un code cellulaire SUPPRN-PN exécuté par la cellule 2 de la figure décrivant le macro-opérateur WRITE. Cet opérateur rend possible l'instruction 'vrite t" o rt" est un tableau. Dans ce cas SUPPRN-PN supprime tous les pointeurs neurones du tableau et connecte tous les éléments du tableau sur la cellule pointeur sortie. Cette figure montre l'effet du code cellulaire SUPPRN-PN exécuté par la cellule 2 de la figure 37, dans le cas o la variable à afficher est un tableau 2D. La figure 56 illustre l'exécution du code cellulaire X-AOR par la cellule 4 de la figure décrivant le macro-opérateur IF. Le résultat est la production d'une couche de neurones AORs et la reproduction des neurones pointeurs structurant les données. Cette couche de neurones récupère soit l'environnement de sortie du corps du THEN ou celui du corps du ELSE, pour le transmettre à l'instruction qui suit Cette figure 56 montre l'effet du code cellulaire X-AOR lorsque l'environnement content un tableau. D'une façon générale, les macro- opérateurs déjà introduits IF, WHILE, X-SYNC, doivent lire et ensuite reconstruire les arbres de pointeurs neurones structurant l'environnement Comme on ne connaît pas a priori la profondeur de ces arbres, la seule façon de procéder est de remonter récursivement le long de ces arbres. Le code cellulaire rend possible l'emploi de procédés récursifs. La lecture d'un tableau comme par exemple a: =t[il, i2] se traduit par un arbre syntaxique inhabituel. L'arbre syntaxique utilisé pour t[i1, i2] est représenté à la figure 57. Cette figure 57 illustre la lecture d'un tableau 2D. L'indice il vaut 1, I'indice i2 vaut 2. Les deux premières couches de neurones ont une sigmoïde égale. Ils renvoient 1 si la somme pondérée des entrées moins le seuil vaut 0, et -1 sinon. Ces neurones ont tous des seuils différents qui sont indiqués à l'intérieur du cercle. La troisième couche de neurones effectue des AND logiques. Sur cette couche, un seul neurone renvoie 1, celui qui correspond à l'élément que l'on veut lire. Tous les autres sont à -1. La quatrième couche de neurones est une couche de neurones EAND, un seul des neurones de cette couche est passant. Il laisse passer l'élément du tableau que l'on désire lire. Enfin un neurone AOR est chargé de collecter la donnée que l'on récupère à la sortie. Le macro-opérateur CALLGEN est presque identique à CALLF, excepté que tous les liens vers les variables globales sont coupés. CALLGEN est expliqué ci-après. La lecture d'un tableau est interprétee comme le résultat d'une fonction "1 lect-index" écrite en code cellulaire prenant d+1 entrées pour un tableau à d dimensions: les d indices et le nom du tableau. la fonction "1 lect- index" renvoie la valeur lue dans le tableau. L'écriture d'un tableau comme par exemple t[il, i2]: = v se traduit par un arbre syntaxique du même genre que pour la lecture d'un tableau. L'écriture d'un tableau à d dimensions est interprétée comme le résultat d'une fonction "1 affect-index" écrite en code cellulaire à d+2 entrées et une sortie qui est un tableau. Les entrées comprennent les d indices, la valeur à affecter, le nom du tableau. La fonction "1 affect-index" renvoie le tableau modifié après l'écriture. La figure 58 illustre l'écriture d'un tableau 2D. L'indice il vaut 1, l'indice i2 vaut 2. Les trois premières couches de neurones sont les mêmes que dans la figure précédente. La quatrième couche contient deux fois plus de neurones EAND. Ces neurones EAND sont disposés par paires. Dans chaque paire un des deux neurones de la paire est passant, l'autre est bloquant Le neurone de gauche est toujours bloquant, excepté dans un seul cas, pour l'élément correspondant à l'indice o l'on veut écrire. La couche de neurones suivante est une couche de neurones AORs. Chaque neurone AOR gère un élément du tableau. Il récupère soit l'ancienne valeur de cet élément, soit la nouvelle valeur v si c'est à cet endroit que l'on écrit. Une structure d'arbre de neurones pointeurs, dont le rôle est de conserver la structure de tableau, vient en dernier. On peut voir sur les figures que les réseaux développés pour lire o écrire dans un tableau sont gros. Lorsque les indices utilisés pour lire ou écrire dans le tableau ne peuvent être connus statiquement, la complexité du i0 réseau développé pour lire ou pour écrire est proportionnelle au nombre d'éléments dans le tableau. Dans le cas contraire, des simplifications sont implémentées et la complexité du sous-réseau ajouté est bornée indépendamment de la taille du tableau. La figure 59 illustre l'exécution du macro-opérateur CALLGEN par la cellule ancêtre du motif invariant. CALLGEN a le même effet que CALL-F, excepté que la cellule 2, qui va exécuter le corps de la fonction écrit en code cellulaire, ne possède plus les connexions vers les variables globales du langage Pascal. On a rajouté une instruction au langage Pascal, cette instruction CALLGEN, qui permet de faire appel à une fonction définie en code cellulaire. Préalablement, au début du programme Pascal doit figurer une instruction "#finclude " qui indique un nom de fichier o doivent se trouver les codes cellulaires des fonctions appelées par CALLGEN. La syntaxe de CALLGEN est la suivante: " : = CALLGEN ("nom-code", ,.... )". Le résultat de l'appel est une valeur rangée dans la variable " ". Le nom "nom-code" indique le nom du code cellulaire que l'on veut développer. " .. " sont des paramètres d'appel. Le macro-opérateur CALLGEN a le même effet que CALL-F, à cela prêt que le corps de la fonction appelée n'est pas défini par un arbre syntaxique mais par un code cellulaire préexistant à la compilation. L'autre différence est qu'avant d'exécuter le corps du CALLGEN tout l'environnement est supprimé. En effet la philosophie de CALLGEN est de permettre de définir un certain nombre de fonctions prédéfinies et réutilisables dans plusieurs contextes, ou d'inclure des réseaux de neurones "briques de base" préappris. Les réseaux développés par un appel CALLGEN n'ont jamais besoin des variables globales. Il est donc plus simple de programmer la suppression des liens reliant les variables globales au niveau de l'exécution du macro-opérateur CALLGEN plutôt qu'à chaque fois, dans le code cellulaire appelé par CALLGEN. Des exemples de fonctions prédéfinies dans l'appendice sont: - la fonction "gauche" rend la partie gauche d'un tableau; - la fonction "droite" rend la partie droite d'un tableau; - la fonction "concat" permet de concaténer deux tableaux; -la fonction "int-to-array" rajoute un pointeur neurone qui introduit une indirection supplémentaire. Si le paramètre passé est un tableau à d dimensions, "int-to-array" renvoie un tableau à d+1 dimensions; -la fonction "array-to-int" supprime un pointeur neurone et enlève une indirection. Si le paramètre passé est un tableau à d dimensions, "int- to-array" renvoie un tableau à d-1 dimensions; - la fonction "randomize" permet d'initialiser un tableau avec des valeurs aléatoires dans {-1, 0, 1}. Un des buts principal du compilateur est de paralléliser automatiquement un programme écrit avec une stratégie de résolution "divide and conquer". Dans cette stratégie, un problème de taille n est divisé en deux sous-problèmes de taille n/2 puis en quatre sous-problèmes de taille n/4 etc... On peut utiliser les fonctions de tableaux définies précédemment pour compiler de tels problèmes. Les fonctions "gauche et droite" permettent de diviser les données contenues dans un tableau en deux parties égales. Pour cela, on répartit les colonnes suivant la première dimension en deux sous-tableaux contenant moitié moins de colonnes. Cela peut fonctionner même si le nombre de colonnes est impair, auquel cas l'un des sous-tableaux a une colonne de plus que I 'autre. Cependant, il faut pouvoir tester de façon statique l'arrêt de la récursion. Dans ces divisions en deux et encore en deux, on s'arrête de diviser les problèmes en sous-problèmes lorsque la taille des sous-problèmes devient un. On applique alors une procédure particulière. Il faut donc pouvoir tester statiquement au moment du développement du réseau de neurones si le nombre de colonnes d'un tableau suivant la première dimension vaut I ou non, et suivant la réponse décider de développer une partie de rarbre syntaxique différente. La syntaxe du IF statique est la même que celle du IF normal, sauf qu'on remplace IF, THEN et ELSE par #IF, #THEN, #ELSE. Toutefois, la condition du #IF est du type t=1 o t est un tableau. Les macro-opérateurs #IF et #THEN testent si le tableau t a une seule ou plusieurs colonnes suivant sa première dimension. Dans un cas la cellule ancêtre lit le sous-arbre gauche du #THEN, dans l'autre cas elle lit le sous-arbre droit. La figure 60 illustre l'exécution du macro-opérateur #IF par la cellule ancêtre du motif invariant. Trois cellules sont crées. La cellule 2 va lire un opérateur IDF-LEC qui lui permet de sélectionner sur laquelle des variables tableau de l'environnement porte le test. La cellule 3 est un neurone qui est utilisé plus tard par la cellule I pour récupérer l'environnement, une fois le test achevé. La cellule 1 exécute la partie suivante de la condition codée par le macro-opérateur #THEN. La figure 61 illustre l'exécution du macro-opérateur #THEN par la cellule 1 de la figure précédente. Apres exécution du macro-opérateur IDF- LEC, la cellule I s'est débloquée et a recopié les liens d'entrée de sa voisine d'entrée numéro 1. La situation est décrite en haut de la figure. Le macro- opérateur teste le nombre de liens entrants de son premier voisin. Ici il vaut deux car le tableau a deux éléments. Si ce nombre est supérieur à un, la cellule 1 positionne sa tête de lecture sur le sous-arbre droit, comme c'est le cas ici. Sinon elle va lire le sous-arbre gauche. Le sous-arbre gauche contient le corps du #THEN, et le sous-arbre droit contient le corps du #ELSE. Exemples de réalisations Dans la suite de la description on propose quelques exemples de compilation qui illustrent le fonctionnement du compilateur et son intérêt Les unités d'entrées du réseau correspondent aux valeurs lues durant l'exécution du programme Pascal. Si dans le programme Pascal l'instruction "read a" apparaît, il y a un neurone d'entrée créé. En positionnant la valeur initiale de ce neurone à v, la valeur de a est initialisée à v. Les unités de sortie correspondent aux valeurs écrites durant l'exécution du programme Pascal. Si l'instruction "write a" apparaît, il y a un neurone de sortie créé. A chaque fois que l'instruction "write a" est exécutée, la valeur de ce neurone est la valeur de a. Il y a un neurone d'entrée particulier appelé "start" utilisé pour démarrer le réseau. Pour faire marcher le réseau, on doit initialiser les unités d'entrées avec les valeurs voulues, puis on relaxe le réseau avec une dynamique à mi-chemin entre parallèle et séquentiel. Compilation de proaramme Pascal standard La figure 62 montre un réseau de neurones pour trier huit nombres compilé avec le programme suivant: program p; type tab = array C[0..] of integer; var t: tab; 1, j, max, aux: integer; begin read (t); while 1 trier. Il y a aussi sept unités de sorties qui correspondent à l'instruction "write (t)". Clairement, on peut voir les deux boudcles encapsulées qui sont représentées par deux jeux de liens récurrents. La figure 63 montre un réseau de neurones pour calculer la suite de Fibonaci, développé jusqu'à une profondeur O, compile avec le programme suivant: program Flbonaccl; var resul:integer;a: integer; function fib(n:lnteger):integer; begin lf-(n≤l) then resul:= else resul:= flb(n-1)+fib(n-2) fi; return (resul); end; begin read (a); vrite (fib (a)); end. Cet exemple illustre le fait que si le programme à compiler utilise les appels récursifs, la profondeur de récursion doit être bornéee, avant que ne commence la compilation. Ici la profondeur de récursion est bornée par quatre, donc ce réseau permet le calcul de "fib(i), i correspond à la valeur initiale de la cellule ancêtre. Utilisation de l'instruction CALLGEN On a ajouté au langage Pascal deux instructions CALLGEN et "#include" qui permettent d'inclure dans le réseau final des petits réseaux dont les poids ont été préalablement ajustés à l'aide d'un algorithme d'apprentissage. Le code de ces réseaux se trouve dans des fichiers dont les noms sont spécifiés par une instruction '#include". Ci-dessous un exemple de programme Pascal utilisant instruction CALLGEN. Le réseau compilé d'un réseau de neurones hybride simulant le comportement d'une bête est montré à la figure 64. #1nclude "bete.a" program bete; type tab=ARRAYEO..19] of integer; tab2=ARRAY[O..9] of integer; var plxel:tab; feature:tab2; position,est_mechant,mouvement:integer; functlon opposer(position:integer):lnteger; begin return(l-position); end; begin read(pixel); feature:=CALLGEN("retin\"e,pixel); position:=CALLGEN('"positionobjet",feature); estmechant:=CALLGEN("predateur",feature); if(estmechant=!) then mouvement:=opposer(position) else mouvement:=O fi; vrite(CALLGEN("moteur",mouvement)); end. Dans le fichier "bete.a" se trouve les codes de plusieurs réseaux en couches. Le réseau "rétine" prends en entrée des pixels et extrait des "features" intéressants. Le réseau "position-objet" détermine à partir de ces "features" la position de l'objet si un objet se trouve dans le champs visuel. Le réseau "prédateur" détermine si l'objet est un prédateur. Le réseau "moteur" commande les quatre pattes de l'animal à partir d'une direction de mouvement L'ensemble du réseau compilé permet de simuler le comportement de fuite de l'animal en face d'un prédateur. Le réseau final "bete" a en entree des pixels, en sortie les neurones moteurs des muscles des pattes. Ce réseau peut être stocké dans une bibliothèque pour être a son tour inclus dans un autre réseau plus grand. Cet exemple illustre la souplesse d'interfacçage entre le langage Pascal et le connexionnisme. Le réseau compilé comprend plusieurs couches de neurones apprises, plus une partie qui est purement symbolique. C'est la partie correspondant à l'instruction IF. Ainsi le compilateur, non seulement peut relier entre eux différents sous-réseaux, mais peut aussi faire des calculs à partir de leurs sorties. Utilisation de l'instruction #IF On ajoute au langage Pascal une instruction #IF #THEN #ELSE qui permet de tester une condifion au moment de la compilation. La condition testée a toujours la même forme. On teste si la première dimension d'un tableau contient plus de une colonne. Cette instruction permet de paralléliser automatiquement un programme écrit avec une stratégie de résolution "diviser pour régner". Dans cette stratégie, un problème de taille n est divisé en deux sous- problèmes de taille n/2, puis en quatre sous-problemes de taille n/4. On utilise toujours l'instruction #IF conjointement avec des fonctions appelées par CALLGEN qui enrichissent la structure de données tableau. Par exemple, "gauche" et "droite" permettent de diviser les données contenues dans un tableau en deux parties égales. "int-to-array" et "array-to-int" permettent de rajouter o de supprimer une indirection. Ci-dessous, un exemple de programme Pascal utilisant l'instruction CALLGEN. Le réseau compilé est un réseau de neurones pour trier huit entiers en parallele. Il est montré à la figure 65. #include "array a" program Trifusion; const infini=1000l; type tab = ARRAY [0..7] of integer; var wv tab; function fusion(t:tab;n:integer; u:tab;m:integer): tab; var v:tab; i,j,a,b:integer; begin v:=CALLGEN("concat",t,u); a:-t[O];b:=u[O]; while(i+j begin read(v); vrite(tri(v,8)); end. La fonction "fusion" est écrite en Pascal standard, la fonction "tri" utilise le Pascal amélioré pour implémenter la stratégie "diviser pour régner'. Le fichier "array.a" contient la bibliothèque des codes cellulaires définissant les fonctions manipulant les tableaux. Le réseau compilé prend en entrée huit réels ou entiers et sort la liste triée. La structure du réseau est assez claire. La première couche de réseaux récursifs sort quatre listes triées de deux nombres chacune, la deuxième sort deux listes triées de quatre nombres. Bien qu'étant récursive, la fonction "tri" se compile en un graphe fini, parce qu'elle est appliquée sur un tableau d'entiers fini. Comme on utilise une stratégie "diviser pour régner", le réseau trie n nombres en un temps O(n), à condition que les neurones puissent faire leurs calculs en parallèle. On compile aussi beaucoup d'autres programmes utilisant la stratégie "diviser pour régner". La convolution, le produit matriciel, le maximum d'une liste d'entiers ou réels sont des programmes qui se compilent tous en un réseau capable d'exécuter la tâche en un temps O(ln(n)). Dans un mode de réalisation de l'invention, ce procédé de compilation a été programmé en langage C. Le logiciel obtenu a pour but de prouver la validité du procédé et de mesurer les performances du produit, c'est- à-dire par exemple le nombre de neurones des réseaux compilés. Il ne se contente pas de fournir le réseau de neurones, il fournit en même temps une représentation graphique de ce réseau. Il n'existe pas d'algorithmes qui permettent d'afficher un graphe quelconque en rendant compte des régularités de ce graphe. Il arrive à rendre compte des régularités du réseau final obtenu. Pour cela, il enregistre l'histoire du développement du réseau, car les régularités du réseau sont inscrites dans l'histoire de son développement. Avantages aDportés par l'invention En présentant l'art antérieur dans le début de la description, on a insisté sur le fait que le procédé de compilation neuronale est un procédé basé sur un paradigme nouveau: la génération automatique de réseaux de neurones à partir d'une description algorithmique. Ce paradigme est à l'opposé exact du courant tout puissant et unilatéral qui, à l'heure actuelle, présente les réseaux de neurones sous l'aspect machine qui apprend toute seule. On a comparé la compilation neuronale à trois sortes de compilateurs qui existent actuellement: les compilateur partant d'un langage de description des réseaux de neurones, les compilateurs de base de règles (Intelligence Artificielle), les compilateurs pour machines parallèles. On va montrer à présent que la compilation neuronale peut reproduire et même améliorer ces trois sortes de compilations. Le procédé de compilation neuronale de l'invention est donc un procédé capable de cumuler en les améliorant les intérêts de ces trois sortes de compilations. L'intérêt d'un langage de description de réseaux de neurones tel que SESAME décrit dans l'article [3] cité précédemment est de faciliter la conception des réseaux de neurones compliqués et de grande taille. Ces langages proposent de définir des réseaux de neurones "briques de base" puis ensuite d'assembler ces briques pour construire des réseaux de neurones plus complexes. Ces demrniers peuvent à leur tour être assemblés etc... Cette conception hiérarchique est très pratique. On veut obtenir le même effet avec la compilation neuronale. Pour ce faire on étend le langage Pascal avec l'instruction CALLGEN, qui permet d'inclure des sous-réseaux de neurones prédéfinis. Préalablement, au début du programme Pascal doit figurer une instruction 'Winclude " qui indique un nom de fichier o doivent se trouver les codes cellulaires des sous-réseaux à inclure. La syntaxe de CALLGEN est la suivante: " : = CALLGEN ("nom-réseau", ,.... )". Le nom "nom-réseau" indique le nom du réseau à inclure. Les neurones de sortie du réseau inclus sont connectés aux neurones représentant la variable " " " ... " sont des paramètres d'appels contenus dans des neurones qui sont connectés aux neurones d'entrée du réseau inclus. Lorsqu'il compile un réseau, le compilateur neuronal produit son code cellulaire, ce code cellulaire peut être stocké dans un fichier. Ainsi le réseau compilé peut être inclus dans un autre réseau de plus grande taille, qui à son tour peut être codé et inclus dans un réseau d'ordre supérieur. Cette technique permet une compilation modulaire et une conception hiérarchique de réseaux de neurones. Mais la compilation neuronale va beaucoup plus loin que des langages de description tel que SESAME. La compilation neuronale fournit la possibilité de combiner des réseaux "briques de base" sans faire référence à des connexions physiques entre réseaux mais en se plaçant à un niveau logique, "soft". Un être humain comprend beaucoup mieux une description "sofr o il suffit de décrire les étapes logiques d'un calcul, plutôt qu'un ensemble de connexions horriblement embrouillées. Ainsi la compilation neuronale permet d'envisager la conception de très grands réseaux. Dans un futur proche, des machines avec des millions de neurones seront disponibles et les avantages d'une description logique et "soft" deviendront évidents. De plus, la compilation neuronale ne se contente pas de fournir le réseau de neurones. Elle fournit en même temps une représentation graphique de ce réseau. Actuellement c'est le seul logiciel permettant d'afficher en général un graphe quelconque de manière claire en rendant compte des régularités de ce graphe. La compilation neuronale est un procédé permettant de compiler un programme Pascal vers un réseau de neurones. Pour compiler une base de règles, utilisés en Intelligence Artificielle, vers un réseau de neurones, il suffit d'écrire la base de règles et le moteur d'inférences en langage Pascal. La compilation neuronale inclut donc les compilateurs de base de règles utilisés dans les systèmes dits "hybrides" qui tentent de combiner Intelligence Artificielle et réseaux de neurones. Cependant la compilation neuronale peut intervenir dans la construction de systèmes hybrides d'une autre facçon. Ce compilateur permet de replacer, dans le même modèle de réseaux de neurones artificiels, de la connaissance sous forme d'algorithme de résolution de problème qui est compilée et de la connaissance provenant d'un apprentissage dans les réseaux de neurones. Le compilateur permet ainsi de construire des modèles hybrides "naïfs" en construisant des réseaux en deux couches. La première couche est apprise et elle est sub-symbolique; elle calcule des symboles en les encrant sur des données d'entrées floues et distribuées. La seconde couche est compilée; elle fait un calcul à partir de ces symboles. Le système hybride obtenu est "naif" car les symboles ne sont pas reliés entre eux. Les exemples numériques qui montrent comment la compilation neuronale réussit à paralléliser automatiquement des problèmes tels que le tri ou la multiplication matrice-vecteur, ou matrice-matrice. La compilation neuronale peut paralléliser les algorithmes du type "diviser pour régner". Ces algorithmes divisent un problème en deux problèmes de taille moitié. Chacun de ces sous- problèmes est alors redivisé en deux sous-problèmes de taille moitié etc. ...DTD: jusqu'à ce qu'on arrive à un problème indivisible, qui lui peut se résoudre en temps constant. Comme les sous-problèmes sont tous indépendants, ils peuvent être résolus sur deux sous-réseaux de neurones différents, en même temps. D'o le parallélisme qui en résulte. Dans sa version actuelle le compilateur neuronal ne peut cependant être considéré comme un compilateur parallèle, car il ne produit pas une suite d'instructions exécutables par un ordinateur parallèle cible précis. Il produit un réseau de neurones. C'est une représentation adaptée à un ordinateur parallèle de par la nature intrinsèquement parallèle d'un réseau de neurones. L'étape finale consiste à allouer ce réseau sur une architecture d'ordinateur parallèle physique. Cette étape doit prendre en compte des considérations de taille mémoire, de communication entre processeurs et de précision arithmétique de calculs. On ne peut donc trop s'avancer en ce qui concemrne la puissance du compilateur neuronal comme compilateur parallèle. Cependant, les réseaux de neurones utilisés ont une structure 3D (trois dimensions). Une des dimensions de cette structure représente le temps. Il paraît possible de projeter le réseau suivant cette dimension, pour allouer le réseau sur une grille 2D de processeurs. On est en train de travailler sur cette demrnière étape avec comme ordinateur cible une carte "DECPerle 1" de Digital Equipment Corporation. Le compilateur neuronal n'est pas totalement un compilateur-paralléliseur car il ne fonctionne que si les algorithmes sont écrits avec une stratégie "diviser pour régner". Cependant beaucoup d'algorithmes peuvent se programmer ainsi et on peut dire que l'avantage de la compilation neuronale par rapport à l'approche traditionnelle décrite dans l'article [4] est que l'utilisateur n'a pas besoin de rajouter des indications dans son programme précisant quel processeur va faire quoi et o vont être stockées les données. Appolication industrielle Le procédé de compilation neuronale de l'invention foumrnit la possibilité de combiner des réseaux "briques de base" sans faire référence à des connexions physiques entre réseaux mais en se plaçant à un niveau fonctionnel. Un être humain comprend beaucoup mieux une description fonctionnelle o il suffit de décrire les étapes logiques d'un calcul, plutôt qu'un ensemble de connexions horriblement embrouillées. Ainsi cette approche permet d'envisager la construction de très grands réseaux de plusieurs millions de neurones. De même qu'à l'heure actuelle, il existe des programmes de plusieurs millions d'octets. Dans un futur proche, des machines avec des millions de neurones seront disponibles et les avantages d'une description fonctionnelle deviendront évidents. Le procédé de compilation neuronal apparaît comme indispensable pour la maîtrise de ces machines. Actuellement il existe beaucoup d'ordinateurs parallèles, mais leur programmation nécessite une certaine expertise et pour cette raison elle n'est pas accessible au grand public. La possibilité de pouvoir programmer un ordinateur parallèle comme un ordinateur séquentiel classique est un enjeu industriel de premier plan. Dans sa version actuelle le procédé de compilation neuronale ne produit pas une suite d'instructions exécutables par un ordinateur parallèle cible précis. Il produit un réseau de neurones. C'est une représentation adaptée à un ordinateur parallèle de par la nature intrinsèquement parallèle d'un réseau de neurones. L'étape finale consiste à allouer ce réseau sur une architecture d'ordinateur parallèle physique. Cette étape doit prendre en compte des considérations de taille mémoire, de communications entre processeurs, de précision arithmétique de calculs. Les systèmes utilisant l'Intelligence Artificielle sont maintenant largement utilisés dans l'industrie. On a pu au cours des années d'application de l'Ilntelligence Artificielle se rendre compte de ses limites. Si l'intelligence Artificielle est capable de manipuler des symboles avec efficacité, elle n'est pas capable d'associer ces symboles au monde réel qui est infiniment bruité, flou et vaste. la tendance actuelle pour dépasser les limites de l'Intelligence Artificielle est de combiner l'Intelligence Artificielle avec un autre procédé qui lui peut gérer une grande quantité de données bruitées. Les réseaux de neurones sont le meilleur exemple de procédé pouvant gérer une grande quantité de données bruitées. Les systèmes hybrides Intelligence Artificielle et réseaux de neurones ont un avenir industriel certain. Le procédé de compilation neuronale de l'invention peut intervenir dans la construction de systèmes hybrides d'une facçon qui est nouvelle. Ce compilateur permet de replacer, dans le même cadre connexionniste, de la connaissance sous forme d'algorithme de résolution de problème qui est compilée et de la connaissance provenant d'un apprentissage dans les réseaux de neurones. Le compilateur permet ainsi de construire des modèles hybrides "naïfs", en construisant des réseaux en deux couches. La première couche est apprise et elle est sub-symbolique, elle calcule des symboles en les encrant sur les données d'entrée floues et distribuées. La seconde couche est compilée. Elle fait un calcul à partir de ces symboles. Ces systèmes hybrides sont qualifiés de "naïfs" car les symboles ne sont pas reliés entre eux. Le procédé de compilation neuronale peut donc combiner intimement les types de connaissance symboliques et sub-symbliques. Ce procédé aura donc certainement sa place dans les systèmes hybrides de l'avenir. APPENDICES A) LEXIQUE Algorithme: Méthode décrite pas à pas pour résoudre un problème. Arbre syntaxique: Arbre obtenu après l'analyse syntaxique d'un programme écrit dans un langage de programmation. Arbre-grammaire: Structure de données d'arbre étiqueté par des opérateurs cellulaires, représente un code cellulaire. Blocage: Une cellule de lecture est dite bloquée si elle doit attendre que toutes ses voisines en entrée soient devenues des neurones avant de pouvoir continuer à se développer. Cellules: Une cellule possède des connexions rentrantes et sortantes numérotées et orientées vers d'autres cellules. Une cellule est donc un noeud d'un réseau appelé réseau de cellules. Une cellule possède des registres: des premiers registres qui lui servent pour se développer; des seconds registres qui stockent les attributs d'un neurone. Une cellule de lecture possède une copie du code cellulaire et une tête de lecture pour lire le code cellulaire en un endroit particulier. Elle peut exécuter des opérateurs appelés opérateurs cellulaires, lus par sa tête de lecture sur le code cellulaire. Elle peut aussi exécuter des macro- opérateurs cellulaires. Un neurone peut être considéré comme une cellule particulière qui a perdu sa tète de lecture. Codage cellulaire: Méthode pour encoder une famille de réseaux de neurones structurés de la même façon. Environnement: L'environnement, en compilation désigne l'ensemble des variables accessibles, en un point donné du programme. Intelligence Artificielle: Dans l'invention, on désigne par "Intelligence Artificielle" des systèmes expert qui fonctionnent à partir d'une base de règles et un moteur d'inférence. Les règles comportent un prédicat à vérifier et une conclusion qui est vraie si le prédicat est vrai. Par exemple, si x est un homme, alors x est mortel. La base de règles traduit un ensemble de connaissances concernant un domaine bien délimité et le moteur d'inférence combine les règles entre elles pour manipuler des symboles et faire des déductions logiques. Par exemple Socrate est un homme donc Socrate est mortel. Langage de programmation: Langage informatique utilisé pour décrire un algorithme. Macro-opérateur: Un macro-opérateur remplace la cellule c qui l'exécute par un graphe d de cellules et de neurones. Ce graphe est rattaché au graphe global de la cellule c par l'intermédiaire des voisines de c. Voisines désignent deux cellules connectées entre elles, directement ou par l'intermédiaire de cellules pointeurs. Un macro-opérateur peut être associé à chaque étiquette de chaque noeud de l'arbre syntaxique d'un programme Pascal. Dans ce cas, le graphe d doit indiquer quelles cellules vont exécuter les opérateurs correspondant aux mots Pascal étiquetant les racines des sous-arbres du noeud étiqueté. Un macro- opérateur peut être interprété comme une règle de réécriture. Pour cette raison on dira qu'un macro-opérateur réécrit la cellule c en le graphe d. Le graphe d est appelé le membre droit du macro-opérateur. Contexte de réécriture: Le contexte de réécriture d'un macro-opérateur est la séquence ordonnée des types de ces cellules voisines. Motif invariant: Supposons que l'environnement contient n variables; le contexte de réécriture d'une cellule par un macro-opérateur vérifie l'invariant suivant: la cellule a n + 2 liens en entrée et 2 liens en sortie; le premier lien en entrée et en sortie pointe vers la cellule pointeur entrée et la cellule pointeur sortie; le deuxième lien en entrée pointe vers une cellule appelée cellule "start", le deuxième lien en sortie pointe vers une cellule chargée de faire la liaison entre le graphe généré par le macro-opérateur et le reste du réseau de neurone en aval; cette cellule appelée cellule "next" peut être un neurone (macroopérateur du type expression) ou une cellule de lecture (macro-opérateur qui modifie I'environnement). Neurone: Un neurone est connecté en entrée et en sortie vers d'autres neurones; il est donc indclus dans un graphe de neurones appelé réseau de neurones; un neurone fait un calcul très simple à partir de ses entrées, puis envoie le résultat vers les neurones voisins en sortie; ce calcul consiste à faire la somme pondérée des entrées, puis à appliquer une fonction appelée sigmoïde; un neurone étendu peut aussi faire le produit ou le quotient de ses entrées. Neurones pointeurs: Ce sont des neurones utilisés uniquement pour structurer des données, en arbres. Ces neurones se trouvent aux noeuds de l'arbre sur les feuilles de l'arbre se trouvent les données. On peut ainsi représenter des tableaux Pascal à plusieurs dimensions, ou des structures (mot clé Pascal record). Neurone start: Ces neurones sont utilisés dans les réseaux compilés. Ils servent à lancer l'activité du réseau et à gérer le renouvellement du flux d'activités à l'intérieur des réseaux de neurones récurrents. D'un point de vue pratique, il est traité comme une variable de l'environnement. Opérateur cellulaire: Un opérateur cellulaire peut diviser, modifier les registres de la cellule qui l'exécute ou gérer l'ordre d'exécution des cellules. Réécriture: Réécrire une structure informatique consiste à remplacer un bout de la structure par un autre, en spécifiant comment les bouts de recollent entre eux. On peut réécrire des mots, des arbres, des graphes. Réseau des cellules: Graphe orienté, les connections partant ou arrivant à un sommet sont ordonnées. A chaque noeud se trouve une cellule. Réseau de neurones: Graphe orienté, à chaque noeud se trouve un neurone. Tête de lecture: Un registre particulier de la cellule. Ce registre contient un pointeur vers un arbre-grammaire, et permet à la cellule de lire sur l'arbre grammaire le prochain opérateur qu'elle aura à exécuter. B) BIBLIOGRAPHIE [1] Amrnaud Giacometti. "Modèles hybrides de l'expertise, mémoire de thèse" (Technical Report, LIFIA-IMAG, 1992). [2] F. Gruau. "Genetic synthesis of boolean neural networks with a cell rewritting developmental process" (Combination of Genetic Algorithms and Neural Networks, 1992). [3] Alexander Linden et Christoph Tietz. "Combining multiple neural network paradigms and applications using sesame" (Intemrnational Joint Conference on Neural Networks, Baltimore, 1992). [4] Hans P. Zima, Peter Brezany, Barbara Chapman et Jan Hulman. "Automatic parallelization for distributed-memory systems: experiences and current research" (European Informatics Congress Systems Architecture, 1993). [5] Richard Stottler et Andrea Henke. "Automatic translation from an expert system to a neural network representation" (International Joint Conference on Neural Networks, Baltimore, 1992). C) COMPLEMENTS TECHNIQUES C.1 Registres des cellules Nom Fonction Tête de lecture Lire en un endroit du code cellulaire Vie Compter le nombre de récursions pour le borner Biais Stocker le biais Sigmo Stocker le type de la sigmoide Dyn Stocker la dynamique Nu-lien Indique un numéro de lien Simplif Indique le niveau de simplifiabilité Fenêtre 4 entiers pour calculer l'endroit o afficher la cellule Type Indique si c'est un neurone ou une cellule de lecture Par ailleurs les liens ont trois registres, pour stocker le poids "weight", I'état "state" et la marque de début de sous-site. Les sites ont un registre appelé divisable. to C.2 Syntaxe du microcodage des opérateurs La grammaire ci-après génère des microcodes d'opérateurs. ::= I I I I ::=TOP I TOP ::= I ::= DIV I DIV ::= I ::= I - I s ::= m I M I r I R I d I D ::= * I > I ≥ I :: =HOM := CELL I SIT I LNK ::= EXE I BRA :: AFF Le non terminal se réécrit en un chiffre, le non terminal se réécrit en un caractère. Ce caractère est pour le non terminal CEL, SIT, LNK le nom abrégé d'un registre de la cellule, du site ou du lien, pour EXE il rappelle quelle sorte de mouvement la tête de lecture fait, pour BRA, il indique le type de condition testée pour décider le branchement, pour AFF il indique quelle type de neurone on a. C.3 Listes des opérateurs et leurs microcodes o10 Le lettre x indique que l'opérateur utilise un argument entier. i est le nombre d'entrées, o est le nombre d'unités de sortie, r est la valeur du registre lien. *************************Transformation topologique locale -* ***** CUTL x TOPm- Cuts the input links i-x CUTRI x TOPm Cuts input link x CLIP TOPm_ Cuts input link r CUTO x - TOPm Cuts output link x MRG x TOPm Merge the input link of input neighbour x MG x TOPm_ Merge the input link of input nelgbour r CPFO x -TOPm - Copy first output of output cell x CHOPI x TOPm= Cut all the input links except link x CHOPO x -TOPm= Cut all the output links except link x CHHL TOPml> Cut the first input links from 1 until i/2 CHHR TOPmI PUTF x TOPmxm Put link x in first position PUTL x TOPm m- Put link x in last position SWITCH x TOPm Sm- Makes a link permutation between last link and link x KILL TOP Delete the neurone CYC TOPs Create a recurrent link **t***Division de cellule en deux filles qui vont exécuter un code séparée PAR DIVd*Re Parallel division SEQ DIVs Sequential division ADL x DIVm Add a cellule on link x AD x DIVm Add a cellule on link r IPAR x DIVm Duplicat link x, Add a cellule on link x SPLFI x DIVd - Duplicate last input starting at link x SPLLIL x DIVsd>- Duplicate last input starting at link i-x XSPL x DIVm Separation division *************Division de cellule en plus de deux filles qui vont exécuter le même code************ CLONE x OLC Clone into x childs, x ls the argument SPLIT HOMO Split Into y childs. y ls computed frou the topology TAB HOMI Saue has aplit, but child i as its bias set to i SPLITN HOM2 Same as split, but the tub-sites are *erged ************ ****************e**Modf du******************** SBIAS x CELb Set the bias to the argument SBIASO CELb O Set the bias to O SBIAS1 CELb 1 Set the bias to 1 INCBIAS CEL+b 1 Increment the bias DECBIAS CEL+b -1 Decrement the bias SSIGMO x CELs Set the type of sigmo\"'{\i}d SDYN x CELd Set the dymamic EVER x CELe Set the level of simplifiability LR x CEL1 Set the link register INCLR CEL+1 1 Increments the link register DECLR CEL+1 -1 Decrements the link register SITE SITD Sets the dlvisability of the sites to the argument SITI SITd Sets the divisability of the input site to the argument SITO -SITd Sets the divisability of the output site to the argument DELSITE SITO Merges all the input sites and all the output sites DELSITI SITo Merges all the input sites DELSITO -SITo Merges all the output site MULTSIT SITn Crates one input site for each input link VAL x LNKv Sets the value of the input weight r to x VALO x -LNKv Sets the value of the output eeight r to x r + VAL+ LNKv 1 Sets the value of the input weight r to 1 - VAL- LNKv -2 Sets the value of the input veight r to -1 INC LNK+v 1 Increments the value of the weight on the input link r DEC LNK+v -1 Decrements the value of the veight on the input link r MULT2 LNK*v 2 Doubles the value of the veight on the input link r DIV2 LNK/v 2 Halves the value of the eeight on the input lhnk r RAND x LNK? Set veight x to a random value in {-1, O, 1} ON LNKs 1 Set the state of the link to on OFF LNKs O Set the state of the link to off *Réalisation de l'ordre exécution - WAIT x EXEw Wait the specified number of steps WAIT EXEf Wait one step if no argument is supplied JMP x EXEj Include a subnetwork which number is the argument JMP EXEj Use a pattern matching mechanisn if no argument is supplied REC EXEr Jump to the currently read subtree END EXEe Become a finished neuron BLOC EXEq Wait for the neigbour to loose their readmng head ;Z? _.; EXEabel ;?:_ LXE_abel - _F EX_ JUsed ti start a new branch that encodes a subnetgork L:-E 3RAf Test if the value of the llfe register is one -_F -- RAg Test if the value of the life reglster is the initial value - E_' x BRAu Test if the nelgbour has x input link 3?N 3RAD Test if the neighbour is a pointer neuron ELR x BRAl Test if the value of the link register equals the argument *************************Mise en valeur de l'affichage du graphe******************** PN AFFpn VAR AFFvar ***********************Opérateurs pour étiquetag e************* DINS EXEf It indicates insertion of the right sub-tree GINS EXEf It indicates insertion of the left sub-tree PN_ CELe It is a pointer neuron VAR_ EXEe It contains the initial value of a variable EAND. EXEe It has a dynamic EAND AOR_ EXEe It has a dynamic AOR INF_ EXEe It compares the 2 inputs SUP_ EXEe It compares the 2 inputs INFEQ_ EXEe It compares the 2 inputs SUPEQ_ EXEe It compares the 2 inputs PLUS_ EXEe It adds the 2 inputs MOINS_ EXEe It substract the one input from the other MULT_ EXEe It multiplies the 2 inputs QUO_ EXEe It divides one input by the other NOT_ EXEe It does a logical NOT OR. EXEe It does a logical OR AND_ EXEe It does a logical AND NEQ_ EXEe It test if both input are different EQ_ EXEe It test if both inputs are equal EQB_ EXEe It tests if input is equal to bias START_ EXEe It is a Start neuron C.4 Syntaxe des arbres syntaxiques utilisés La grammaire ci- après génère des expressions entre parenthèses qui sont interprétables en des arbres syntaxiques corrects. Un arbre syntaxique peut être celui d'un programme, celui d'une procédure ou celui d'une fonction. Le compilateur doit générer un ensemble d'arbres.un arbre pour le programme principal et un arbre pour chaque fonction ou procédure. La représentation entre parenthèses utilisée ici est inhabituelle. On omet de mettre des parenthèses lorsqu'il y a un seul sous-arbre, on se contente de mettre un blanc. Lorsqu'il y a deux sous-arbres, on considère qu'il y a un tronc qui part à droite et une branche qui part à gauche. Seule labranche est mise entre parentheses. Cette représentation spéciale permet, de décrire les arbres syntaxiques avec une grammaire simple. Les lettres majuscules et les parenthèses sont des terminaux. Les non-terrninaux sont écrits avec des lettres minuscules entre crochets. := I I ::= PROGRAM ::= PROCEDURE ::= FUNCTION ::= DECL attrb ( ) I ::= TYPEARRAY attrb I TYPESIMPLE ::= SEMICOLON (inst) I ::= SEMICOLON ( ) I RETURN ::= I I I I I I I I ::= ASSIGN(IDF_AFF attrb) read>::= READ attrb IDF-AFF attrb ::= WRITE if>::= IF( ) ::= THEN ( ) ::= #IF( ) ::= #THEN ( ) ::= WHILE ( ) ::= REPEAT ( ) ::= CALLP attrb ::= COMA ( ) I NOPARAM ::= CALLGEN attrbO :: I I I 2S I I I :: CALLGEN attrbl : CALLGEN attrb2 : IDF.LEC attrb : INTCST attrb : BINOP attrb ( ) ::= UNOP attrb : CALLF attrb Cette grammaire génère des arbres syntaxiques avec des noeuds ayant parfois des attributs. Cidessous, on indique la nature de chaque attribut. Nom Rôle de l'attribut DECL Nom de la variable déclarée TYPE- ARRAY Dimension du tableau IDF-AFF Nom de la variable à affecter IDF-LEC Nom de la variable à lire INT-CST Valeur de la constante entière CALL-P Nom de la procédure à appeler CALL-F Nom de la fonction à appeler CALL-GEN AttrbO est le nom d'une procédure précodée CALL-GEN Attrbl est le nom d'une procédure précodée qui permet de lire un tableau CALL- GEN L'attribut attrb2 est le nom d'une procédure précodée qui permet d'écrire un tableau BINOP Nom de l'opérateur binaire UNOP Nom de l'opérateur unaire C.5 Mode d'emploi du compilateur Le compilateur s'appuie sur une base de règles et de prédéfinitions qui sont reportées dans les sections suivantes. Cela est pratique pour la mise au point car, pour modifier le compilateur, il suffit de modifier ces deux bases et il n'est pas nécessaire de recompiler les sources. Le logiciel obtenu a plusieurs options: 15. I'option "-r " (changement de fichier de base de règles à utiliser); I'option "-p " (changement de fichier des prédéfinitions à utiliser); l'option "-m" qui permet la création d'un fichier.lib contenant les codes cellulaires des fonctions déclarées dans le programme. Ces codes cellulaires peuvent être ensuite appelés directement avec CALLGEN. Cette option permet ainsi de faire de la compilation modulaire. De même qu'un compilateur de langage évolué génère du langage machine, le compilateur génère un code cellulaire qui est développé par un autre logiciel indépendant. Celui-ci permet non seulement de développer le réseau codé, mais aussi de voir le réseau compilé ainsi que les étapes de développement sur une fenêtre XII1. De nombreux boutons servent à piloter le développement, à gérer les entrées/sorties du réseau compilé, à voir les contenus des différents registres des cellules et à agrandir avec une loupe une partie du dessin du réseau. C.6 Prédéfinitions Ces prédéfinitions sont des bouts de codes cellulaires permettant de factoriser les codes cellulaires membres droits des règles de réécriture de la grammaire d'arbres. C.6.1 Opérateurs arithmétiques On liste ici des bouts de codes qui implémentent des opérateurs arithmétiques sur des neurones, ainsi que les dynamiques AOR et EAND. Les sigmoides sont, par ordre de numéro croissant: identité (1), Pi-Unit (3), marche-escalier-L (5), marche-escalier-R (6), égalité à zéro (7), Div-Unit (8). OR OR SBIAS 2 (SSIGMO 5 MARCHE-ESCALIER-L (OR-)) AND AND SSIGMO 5 MARCHE-ESCALIER-L (AND-) NEG NEG LR 1 (VAL-1 (NOT-)) INFEQ INFEQ LR 1 (VAL -1 (SSIGMO 6 MARCHE-ESCALIER-R (INFEQ-))) SUPEQ SUPEQ LR 2 (VAL -1 (SSIGMO 6 MARCHE-ESCALIER-R (SUPEQ-))) INF INF LR 1 (VAL -1 (SSIGMO 5 MARCHE-ESCAULIER-L (INF-))) SUP SUP LR 2 (VAL -1 (SSIGMO 5 MARCHE-ESCALIER-L (SUP-))) EQ EQ LR 1 (VAL -1 (SSIGMO 7 EGALITE-A-ZERO (EQ-))) NEQ NEQ SEQ (JMP EQ) (JMP NEG) PLUS PLUS SSIGMO 1 IDENTITE (PLUS-) MOINS MOINS LR 2 (VAL -1 (SSIGMO 1 IDENTITE (MOINS-))) MULT SSIGMO 3 PI Unit (MULT-) QUO SSIGMO 8 DIV Unit (QUO-) EOR AOR SDYN 2 (AOR-) EAND EAND SDYN 3 (EAND-) C.6.2 Lecture écriture-dans un tableau On présente les codes cellulaires des fonctions permettant de lire et d'écrire dans un tableau à plusieurs dimensions. Chacune de ces fonctions nécessite trois bouts de codes qui s'appellent chacun eux-mêmes récursivement. 1AFFECT-INDEX SITE 1 (CUTLE 3 (CUTO 1 (MULTSIT (SEQ (ADL 1 (SITE 0 (JMP CREAT-EQB)) (MRG-2 (SPLIT (JMP 1AFFECT-SUIT)))) (SITE 0 (BLOC (PN2))))))) CREAT-EQB TAB (VAL -1 (SSIGMO 7 (EQB-))) 1AFFECT-SUIT BUN 3 (JMP 2AFFECT-SUIT) (SEQ (SPLLIL 3 (SITE 0 (CUTRI 3 (ADL 2 (JMP CREAT-EQB) (SPLIT (JMP AND))))) (MRG -2 (SPLIT (JMP 1AFFECT- SUIT)))) (SITE 0 (BLOC (PN -2)))) 2AFFECT-SUIT BPN 2 (SITE 0 (JMP 3AFFECT-SUIT)) (MRG 3 (MRG 2 (SEQ (SPLIT (JMP 2AFFECT-SUIT)) (SITE 0 (BLOC (PN -2)))))) 3AFFECT-SUIT SEQ (PAR (CUT 3 (LR 1 (VAL -1 (JMP EAND)))) (CUT 2 (JMP EAND))) (JMP AOR) i INDEX-LEC SITE I (CUTLE 3 (CUTO I (MULTSIT (SEQ (ADL 1 (SITE 0 (JMP CREAT-EQB)) (MRG -1 (SPLIT (JMP 1 INDEX-SUIT)))) (BLOC (JMP 2INDEXSUIT)))))) 1INDEX-SUIT BUN 2 (JMP SUPER-EAND) (SPLLIL 3 (SITE 0 (CUTRI 3 (ADL 2 (JMP CREAT-EQB) (SPLIT (JMP AND))))) (MRG -1 (SPLIT (JMP 1 INDEX- SUIT)))) 2INDEX-SUIT SPLIT (BPN 1 (JMP AOR) (SEQ (LR -1 (JMP SUPER-MRG)) (SITE 0 (BLOC (PN -2))))) C.6.3 Macrocode On liste ci-joint des bouts de codes qui sont utilisés à plusieurs endroits dans le code cellulaire. Ces bouts de codes appliquent des opérateurs récursivement sur tout l'environnement SUPER-MRG BLR 0 (MG (ADDLR - 1 (JMP SUPER-MRG))) (JMP 2INDEX-SUIT) la macro SUPER-EAND SUPER-EAND SPLIT (BPN 2 (JMP EAND) (MRG 2 (SEQ (JMP SUPER-EAND) (SITE 0 (BLOC (PN- 2)))))) la macro SUPER-AOR SUPER-AOR SEQ (MRG 2 (MRG 1 (SPLIT (BPN 1 (JMP * AOR) (JMP SUPER-AOR))))) (SITE 0 (BLOC (PN- 2))) la macro SUPER-DYN SUPER-DYN SPLIT (BPN 1 (EVER 1 (SDYN 2)) (SEQ (MRG 1 (JMP SUPER-DYN)) (SITE 0 (BLOC (PN- 2))))) la macro SYNCHRO SYNCHRO IPAR 1 (VAL 0 (EVER 0)) (SITE 0 (BLOC (DELSITO (SPLITN (EVER 1))))) la macro REPEAND REPEAND SPLIT (BPN 2 (JMP EAND) (MRG 2 (JMP REPEAND))) la macro WHILEND WHILEND SPLIT (BPN 1 (END) (MRG 1 (JMP WHILEND))) la macro READ-SUIT READ-SUIT BPN 3 (CUT 3 (LR 2 (VAL 0))) (SEQ (MRG 3 (SPLIT (JMP READ-SUIT))) (SITE 0 (BLOC (PN- 2)))) la macro WRITE-SUIT WRITE-SUIT BPN 1 (END) (MRG 1 (SPLIT (JMP WRITE- SUIT))) C.7 Règles de réécriture des noeuds de l'arbre syntaxique IF SITE 1 (SPLLIL 1 (CPFO I (SITE 0 (DELSIT (RINS)))) (SEQ (SITE 0 (SPLF1 2 (CUT 2 (PAR N(WAIT 2 (SITE 1 (JMP SUPER-EAND))) (ILR 1 NOT SIMPLIFIE (VAL -1 (SITE 1 (JMP SUPER-EAND)))))) (CUT 1 (CPFO 1 (LINS))))) (BLOC (CUTO 1 (JMP SUPER-AOR))))) THEN PAR (CUT 3 (BLOC (DELSIT (RINS)))) (CUT 2 (BLOC (DELSIT (LINS)))) REPEAT SITE I (CYC (SITE 0 (XSPL 1 (SITE 1 (JMP SUPER-DYN)) (SPLFI 1 (CPFO 1 (BLOC (DELSIT (RINS)))) (BLOC (MRG 2 (SITE I (SPLLIL 2 (CPFO 1 (SITE 0 (DELSIT (LINS)))) (PAR (CUTO 1 (CUTO 1 (LR 1 (VAL -1 (SEQ (WAIT 2 (JMP REPEAND)) (JMP SYNCHRO)))))) (CHOPO 2 (SEQ (JMP SUPER-EAND) (SITE 0 (BLOC (END)))))))))))))) WHILE SITE 1 (CYC (SITE 0 (XSPL 1 (SITE 1 (JMP SUPER-DYN)) (BLOC (SITE 1 (SPLLIL 1 (CPFO 1 (SITE 0 (DELSIT (LINS)))) (PAR (CUTO 2 (SPLFI 2 (CUT 2 (JMP SUPER-EAND)) (SITE 0 (CUT 1 (BLOC (SEQ (CPFO 1 (RINS)) (BLOC (SITE 1 (CUTO 1 (SEQ (MRG 1 (WAIT (JMP WHILEND))) (JMP SYNCHRO))))))))))) (CHOPO 2 (LR 1 (VAL -1 (SEQ (CUT 2 (JMP SUPER-EAND)) (SITE 0 (BLOC (END)))))))))))))) PROGRAM IPAR 1 (START-) (SEQ (CPFO 1 (SWITCH 1 (LINS))) (BLOC (MRG 1 (CUTO 1)))) NO-INST CUTO 1 (CUT 1) DECL IPAR 2 (RINS) (PUTL 2 (BLOC (LINS))) TYPE-ARRAY SEQ (CLONE ATTR (LINS)) (BLOC (EVER 2 (PN))) TYPE-SIMPLE VAR (LR 1 (VAL 0 (EVER 2))) SEMICOL SPLFI 1 (CPFO 1 (LINS)) (BLOC (MRG 2 (RINS))) ASSIGN SPLFI 1 (CPFO 1 (RINS)) (BLOC (LINS)) IDF-AFF SWITCH attr (CUTL 1 (CUT 1 (CUTO 1))) IDF-LEC CUTO 1 (CHOP attr (BPN 1 (END) (MRG 1 (PN- 2)))) COMMA PAR (LINS) (RINS) UNOP SEQ (CPFO 1 (LINS)) (CUTO 1 (JMP attr)) BINOP SEQ (CPFO 1 (PAR (LINS) (RINS))) (CUTO 1 (JMP ATTR)) INT-CST CHOP 2 (CUTO 1 (SBIAS ATTR (LR 1 (VAL 0 (EVER 2))))) CALL-F SPLFI GLOBAL (CPFO 1 (RINS)) (BLOC (JMP ATTR (CUTO 1 (CHOP 2 (LR 1 (VAL 0)))))) NO-PARAM KILL 0 FUNCTION ou RETURN LINS 0 CALL-P SPLLI LOCAL (CPFO 1 (SPLFI GLOBAL (CPFO 1 (RINS)) (BLOC (JMP ATTR (END))))) (BLOC (MRG 1 (CUTO 1))) PROCEDURE SEQ (CPFO 1 (LINS)) (BLOC (MRG 1 (CUTRI GLOBAL (CUTO 1)))) READ SPLFIL 1 (SPLFI 2 (CHOP ATTR) (MRG 3 (SITE 1 (MULTSIT (JMP READ-SUIT))))) (BLOC (RINS)) WRITE PAR (CHOPO 1 (SEQ (CPFO 1 (RINS)) (BLOC (JMP WRITE- SUITD))) (CUT 1 (CUTO 1)) # IF SEQ (CPFO 1 (PAR (CUTO 1) (RINS))) (BLOC (MRG 2 (LINS))) # THEN BUN ATTR (CHOP 1 (MRG 1 (RINS))) (CHOP 1 (MRG 1 (LINS))) CALLGEN SPLFI 2 (CPFO 1 (RINS)) (BLOC (JMP AUI-R (CUTO 1 (CHOP 2 (LR 1 (VAL 0)))))) C.8 Bibliothèque de fonctions pour manipuler les tableaux gauche CUTLE 3 (CUTO 1 (MRG I (CHHR 1 (PN- 2)))) droite CUTLE 3 (CUTO 1 (MRG 1 (CHHL 1 (PN- 2)))) concat CUTLE 3 (CUTO 1 (MRG 2 (MRG 1 (PN- 2)))) int-to-array CUTLE 3 (CUTO 1 (PN- 2)) array-to-int CUTLE 3 (CUTO 1 (MRG 1 (BPN 1 (END) (MRG 1 (PN- 2))))) randomise CUTLE 3 (CUTO 1 (JMP rand)) rand BPN 1 (LR 1 (VAL 0 (RAND))) (SEQ (MRG 1 (SPLIT (JMP rand))) (PN- 2)) C.9 Réseaux de neurones inclus dans béte.p rétine CUTLE 3 (CUTO 1 (SEQ (MRG 1 (SPLIT)) (SEQ (CLO 10 (EVER 0)) (BLOC (PN- 2))))) position-objet CUTLE 3 (CUTO 1 ( (SE(SEQ (MRG 1 (CLO 2 (EVER 0))) (CLO 2 (EVER 0))) (EVER 0))) prédateur CUTLE 3 (CUTO 1 (SEQ (SEQ (MRG 1 (CLO 3 (EVER 0))) (CLO 3 (EVER 0))) (EVER 0))) moteur CUTLE 3 (CUTO 1 (SEQ (EVER 0) (SEQ (CLO 2 (EVER 0)) (SEQ (CLO 4 (EVER 0)) (PN- 2))))) C.10 Modifications syntaxiques et sémantiques 20. L'instruction RETURN doit être la dernière instruction du corps d'une fonction. On ne peut définir de procédures ou fonctions à l'intérieur d'une procédure ou d'une fonction (comme dans le langage C). On ne peut pas passer de paramètres par variables. Tous les paramètres sont passés par valeur. On ne peut faire d'allocation dynamique de mémoire. On peut compiler la récursivité, jusqu'à une certaine profondeur, qui doit être spécifiée à l'avance, à moins qu'il soit possible de connaître la profondeur nécessaire avant la compilation. C'est le cas pour les algorithmes du type "diviser pour régner". Les fonctions peuvent retourner une valeur qui est un tableau. Le Pascal est complété par les instructions: CALLGEN #include #IF # THEN # ELSE. C. 11 Modification de l'arbre abstrait Les arbres syntaxiques que l'on utilise ont été obtenus à partir d'un arbre abstrait classique en faisant les modifications suivantes: 5. remplacer un noeud IDF par IDF- LEC et IDF-AFF suivant que la variable est lue ou écrite; créer des noeuds particuliers READ et WRITE pour les appels de ces fonctions; implémenter les écritures et lectures dans un tableau à l'aide de fonctions particulières: index-lecl et affect-index1; créer des noeuds pour la déclaration de variables, avec leur type codé en utilisant une chaîne d'opérateurs TYPE-ARRAY terminée par un opérateur TYPE-SIMPLE. C.12 Simplifications du réseau de neurones Lors du développement du réseau, les neurones peuvent se simplifier. Pour cela, le voisinage de chaque neurone est examiné. A partir du voisinage, on peut déterminer si le neurone peut être supprimé ou non. Après la suppression du neurone, on rétablit les connexions nécessaires pour que le réseau fonctionne normalement. Les conditions de suppression sont les suivantes: le neurone n'a pas de liens en sortie; le neurone n'a pas de liens en entrée; 25. le neurone a une seule entrée et sa sigmoide est l'identité; le neurone est un EAND toujours passant ou toujours bloquant; le neurone a une sortie constante et on peut le supprimer en ajoutant un biais à ses voisins en sortie; 30. le neurone est un AOR connecté à deux EAND eux-mêmes connectés à deux mêmes neurones, le premier étant un booléen, le deuxième une valeur réelle ou entière. On peut tout simplifier de la même façon que l'on simplifie la formule logique (A AND B) OR (A AND (NOT B) = A. Certains neurones spéciaux ne supportent pas ces simplifications. Les neurones pointeurs ne se simplifient pas même s'ils calculent l'identité et ont un seul lien en entrée. Les neurones d'entrée ne se simplifient pas même si ils n'ont pas de liens en entrée, les neurones de sorties ne se simplifient pas même si ils n'ont pas de liens en sortie. Pour gérer les simplifications, on positionne leurs registres "simplirf sur une valeur élevée. A chaque simplification est attribué un numéro. Un neurone est simplifié seulement si le numéro de la simplification qu'on veut lui appliquer est inférieur à la valeur de son registre "simplif". Il est surprenant de voir à quel point les simplifications permettent de réduire la taille des réseaux de neurones. Le compilateur génère en effet beaucoup de neurones inutiles. Fréquemment, après les simplifications, le nombre de neurones est divisé par trois. REVENDICATIONS 1. Procédé de conception d'un réseau de neurones à partir d'un programme d'ordinateur écrit dans un langage procédural décrivant les étapes logiques de résolution d'un problème, caractérisé en ce qu'il comprend les étapes suivantes: - on-définit (10) une cellule comportant: * des premiers registres utilisés pour le développement de la cellule, * des seconds registres utilisés pour mémoriser des étiquettes qui représentent les attributs d'un neurone, * des connexions pondérées pour relier les cellules entre elles de façon ordonnée et orientée; -on définit (11) un graphe "initial" de cellules formé de trois cellules, une cellule de lecture appelée "cellule ancêtre" et deux neurones pointeurs aptes à classer les neurones par rangée; - on développe (12) un graphe de cellules qui est un ensemble de cellules reliées entre elles avec des connexions pondérées orientées et ordonnées dont l'architecture finale décrit le programme; - on construit (13) I'arbre syntaxique du programme écrit en langage procédural, cet arbre comportant des étiquettes correspondant chacune à un mot du langage procédural; - on définit (14) un ensemble de transformations locales de graphes de cellules appelées "macroopérateurs" pouvant être munis d'un paramètre, un macro-opérateur étant la transposition de chaque mot du langage procédural; - on réalise (15) la décomposition des macro-opérateurs suivant un ensemble de petites transformations locales de graphes de cellules appelées "opérateurs cellulaires" qui assemblées forment un code cellulaire par application de tableaux et obtention de codes cellulaires relatif à chaque macro- opérateur; -on modifie (16) l'arbre syntaxique de façon à associer à chaque étiquette de l'arbre syntaxique un macro-opérateur muni ou non de paramètres par application d'un tableau; - on réalise (17) la décomposition des macro-opérateurs en un arbre d'opérateurs cellulaires; on réécrit (18) l'arbre syntaxique modifié en remplaçant chaque macroopérateur par son code cellulaire et on obtient le code cellulaire d'un réseau de neurones correspondant au programme écrit dans le langage procédural; - on décode (19) le code cellulaire en appliquant les opérateurs du code cellulaire sur le graphe initial; - on obtient (20) le réseau de neurones. 2. Procédé selon la revendication 1, caractérisé en ce qu'on utilise des neurones ayant des dynamiques particulières aptes à diriger les flux de données dans le réseau de neurones à partir des instructions du programme écrit dans le langage procédural dirigeant les flux de données. 3. Procédé selon la revendication 1, caractérisé en ce qu'on a un ensemble de couches formées par des neurones indépendants les uns des autres, chaque couche contenant les valeurs de toutes les variables à un instant donné, le nombre de neurones par couche étant égal à celui des variables déclarées dans le programme, chaque instruction ayant un sous réseau de neurones. 4. Procédé selon la revendication 3, caractérisé en ce que pour la compilation d'un sous réseau, les macro-opérateurs du sous-arbre syntaxique modifié de chaque instruction génèrent une transformation de graphe qui transforme un cellule en un sous-réseau calculatoire SRi; en ce que pour N instructions on a N + 1 couches C1... Cn+1; en ce que l'instruction i est compilée en un sous-réseau de neurones intercalé entre les couches Ci qui contient les valeurs des variables avant la réalisation de l'instruction i, et Ci+1, qui contient les valeurs des variables après l'exécution de l'instruction i; en ce que l'on réalise la connexion de la couche Ci au sous-réseau, les neurones de Ci correspondant aux variables lues par l'instruction i vers les neurones du sous- réseau qui font faire les calculs en utilisant directement ces valeurs; et en ce que l'on réalise la connexion du sous-réseau à Ci+1, les connexions des neurones du sous-réseau contenant les résultats des calculs vers les neurones de Ci+1 correspondant aux variables modifiées; en ce que ces opérations ont lieu, pour chaque couche, pour tout le programme écrit dans le langage procedural. 5. Procédé selon la revendication 1, caractérisé en ce que l'on utilise quatre sortes de macro-opérateurs: - un qui est apte à créer un invariant, c'est-à-dire qu'ils donnent des voisins à la cellule ancêtre; toute cellule connectée à un macro- opérateur étant connectée aux mêmes cellules voisines dans le même ordre. Ces cellules voisines correspondant à cette caractéristique étant appelées invariant; - ceux qui créent un sous-réseau de neurones calculatoires, aptes à faire des calculs; les macro-opérateurs du sous- arbre syntaxique modifié de chaque instruction générant une transformation de graphe qui transforme une cellule en un sous réseau calculatoire SRi; - ceux qui créent une couche de neurones; les macro- opérateurs du sous-arbre syntaxique modifié de la partie déclaration de variables du programme écrit dans un langage procédural générant une transformation de graphe qui transforme une cellule vérifiant l'invariant en une couche initiale de neurones; - ceux qui combinent pour chaque niveau les deux couches précédentes; les macro-opérateurs de l'arbre syntaxique modifié qui servent à séquencer les déclarations et instructions entre elles, ces macro-opérateurs générant des transformations de graphe et/ou des mouvements de tête de lecture d'un arbre à l'autre aptes à combiner les réseaux SRi entre eux ainsi que les couches Ci. 6. Procédé selon la revendication 5, caractérisé en ce qu'on utilise un macro-opérateur CALLGEN qui a la syntaxe suivante " = CALLGEN ("nom-code", ,..., )", le résultat de l'appel étant une valeur rangée dans la variable " ", le nom "nom-code" indiquant le nom du code cellulaire que l'on veut développer, " ... contextes, ou d'inclure des réseaux de neurones "briques de base" préappris. 7. Procédé selon la revendication 6, caractérisé en ce qu'on utilise un macro-opérateur # IF qui permet de tester une condition au moment de la compilation, la condition testée ayant toujours la même forme, en ce qu'on teste si la première dimension d'un tableau contient plus de une colonne, en ce que cette instruction permet de paralléliser automatiquement un programme écrit avec une stratégie de résolution "diviser pour régner", en ce que dans cette stratégie, un problème de taille n est divisé en deux sous-problèmes de taille n/2, puis en quatre sous-problèmes de taille n/4, et en ce q'uon utilise toujours l'instruction # IF conjointement avec des fonctions appelées par CALLGEN qui enrichissent la structure de données tableau. 8. Procédé selon la revendication 5, caractérisé en ce qu'on met en évidence un motif invariant qui est le contexte de réécriture, en ce que si l'environnement contient n variables, la cellule a n+2 liens en entrée et 2 liens en sortie, le premier lien en entrée et en sortie pointant vers la cellule pointeur entrée et la cellule pointeur sortie, le deuxième lien en entrée pointant vers une cellule appelée cellule "start', le deuxième lien en sortie pointant vers une cellule appelée cellule "next" qui est ou bien un neurone (macro-opérateur du type "expression'), ou bien un ecellule de lecture de lecture bloquée (macro- opérateur du type "modification de l'environnement), la cellule "next" étant chargée de faire la liaison entre le graphe généré par le macroopérateur et le reste du réseau de neurones en aval. 9. Procédé selon la revendication 1, caractérisé en ce qu'on utilise des structures de données tableau permettant la définition des tableaux, leur écriture et leur lecture, le neurone pointeur étant apte à représenter la structure de données tableau dans le graphe de cellule durant l'étape de décodage. 10. Procédé selon la revendication 1, caractérisé en ce qu'on réalise la traduction d'un langage qui est une combinaison d'un langage de programmation "procédurale" et d'un langage de description de réseau de neurones; et en ce que ledit procédé comporte une étape préliminaire de construction de codes cellulaires de réseaux de neurones de façon à rendre l'accès à partir de ce langage à une bibliothèque de fonctions apte à être traduite en des réseaux de neurones optimisés en termes de nombre de neurones et de rapidité d'exécution. 11. Procédé selon la revendication 10, caractérisé en ce que la construction de codes cellulaires de réseaux de neurones comporte une étape d'apprentissage des poids des connexions des neurones des réseaux de façon à calculer une fonction quand on ne connait pas la procédure calculatoire simple, en connaissant le résultat pour une base d'exemples particuliers. 12. Procédé selon la revendication 10, caractérisé en ce que l'étape préliminaire de construction des codes cellulaires comprend les étapes suivantes: - construction de codes cellulaires de réseaux de neurones dont l'architecture reflète les particularités du problème à résoudre et dont les poids ne sont pas ajustés; - décodage du code cellulaire pour construire le réseau de neurones; - apprentissage du réseau à partir de la base d'exemples du problème à résoudre de façon à modifier les poids du réseau et/ou l'architecture; - rétrocodage du réseau en fonction des modifications et obtention d'un code cellulaire modifié aDte à coder le réseau de neurones modifié par l'apprentissage. 13. Procédé selon la revendication 10, caractérisé en ce qu'on complète le langage combiné avec une bibliothèque de fonctions permettant de faire de la parallélisation automatique de programme en langage procédural, ledit procédé étant apte à traduire un programme écrit dans un langage de spécification avec une stratégie "diviser pour régner" en un réseau de neurones aptes à exécuter des calculs en parallèle en utilisant une bibliothèque qui définit des codes cellulaires calculant des fonctions de tableaux. 14. Procéde selon la revendication 1, caractérisé en ce qu'on définit un ensemble de microtransformations locales de graphes de cellules appelées "microcodes" qui assemblées forment des opérateurs cellulaires de division et de modification locale de la topologie du graphe; et en ce que l'on étend les microcodes de façon à microcoder tous les opérateurs cellulaires. 15. Procédé selon la revendication 14, caractérisé en ce que le procédé d'écriture d'une procédure, permettant d'implanter le procédé de traduction d'un programme écrit dans un langage procédural, utilise de façon indépendante une base de règles de réécriture de l'arbre abstrait et une procédure appliquant ces règles; en considérant trois fichiers: - un qui comprend le code qui permet la réécriture d'arbres; - un qui comprend les règles de réécriture; - un qui content les prédéfinitions qui sont des morceaux de code cellulaire définis séparément, chaque code cellulaire pouvant être exprimé sous forme d'une combinaison de ces prédéfinitions 16. Procédé selon la revendication 14, caractérisé en ce que le procédé de décodage utilise un microcodage qui permet d'implanter de façon efficace le procédé de décodage, la liste des microcodes des opérateurs étant définie séparément dans des fichiers indépendants de la procédure de décodage. 17. Procédé selon la revendication 1, caractérisé en ce qu'on utilise des opérateurs permettant d'implanter les macro-opérateurs en décomposant la transformation de graphe correspondante en une transformation de graphe plus petite. 18. Procédé selon la revendication 17, caractérisé en ce que l'ensemble des opérateurs cellulaires comprend en outre: - un opérateur BLOC qui permet le blocage du développement de la cellule durant l'étape de décodage du code cellulaire; - un opérateur JUMP qui permet de décomposer un code cellulaire en plusieurs arbres, chaque arbre codant un réseau de neurones pour ensuite décomposer les différents réseaux de neurones de façon hiérarchique et modulaire; - un opérateur SPLIT, appliqué à une cellule donnée qui génère un nombre de cellules égal au cardinal du plus gros paquet de liens de la cellule auquel il est appliqué; - un ensemble d'opérateurs qui testent une condition portant sur l'état du registre ou de la connectivité de la cellule qui exécute un tel opérateur suivant le résultat une condition donnée, la cellule plaçant sa tête de lecture sur le sous arbre gauche ou le sous arbre droit.