====== Tutoriel : les propriétés logiques ====== L'objectif du tutoriel est de présenter les propriétés logiques élémentaires. Bien que ces propriétés puissent se combiner, la présentation de propriétés logiques se veut minimaliste afin d'illustrer au mieux les mécanismes du langage : - [[tutoriel:proprietes_logiques#Logique d'ordre 0]] - [[tutoriel:proprietes_logiques#Logique floue]] - [[tutoriel:proprietes_logiques#Logique non-monotone]] - [[tutoriel:proprietes_logiques#Logique temporelle]] - [[tutoriel:proprietes_logiques#Logique révisable]] Le tutoriel sur les propriétés logiques repose sur l'utilisation du banc d'essais [[nomoSDk:bancs_essais#le_monde_de_dalles|monde de dalles]] avec la carte //tutorial_1.map//. L'image ci-dessous illustre cet environnement avec la position initiale de l'agent : {{ :tutorial:tutorial_1_map.png?nolink&300 |}} Cet environnement sera modifié au cours des exemples. Tous les fichiers utilisés par ce tutoriel se trouvent dans le répertoire "nomoSDK/tutorial/tutorial_1". La [[doc:langage_nomo#le_moteur_d_inference|configuration du moteur d'inférence]] (//tutorial_1.eng//) et celle de [[doc:langage_nomo#la_base_de_connaissances|la base de connaissances]] (//tutorial_1.bas//) qui correspondent à celles par défaut dans [[:nomoSDK]] sont également identiques dans toute cette partie du tutoriel. Au cours de ce tutoriel un seul modèle sera utilisé. Un [[doc/langage_nomo#les_modeles|modèle]] définit le type de règles pouvant êtes exprimées ainsi que l'ensemble de définition de leur contenu. Le modèle du tutoriel (//tutorial_1.mod//) a pour [[doc:langage_nomo#la_base|base]] //worldsquare.mod// détaillé dans la présentation du [[nomosdk:bancs_essais#le_modele_de_nomo_de_base|monde de dalles]]. Ce modèle sera complété au fur et à mesure des exemples. ... Une description complète des différentes sortes de règles et de leur structure se trouve [[doc:base_de_connaissances#la_base_de_regles| dans la partie base de connaissances de la documentation]] et leur traduction en langage nomo se trouve [[doc/langage_nomo#les_schemes_et_les_regles|dans la partie hyponyme de la documentation]]. Les aspects dynamiques n'étant pas abordés, toutes les règles auront un nombre d'ajustements infini (//**fitting_nbr**=“INF”//) et une pertinence maximale (//**relevance**=“1”//). Ces valeurs correspondent aux valeurs par défaut quand elles ne sont pas précisées dans les règles. ===== Logique d'ordre 0 ===== La logique d'ordre 0 ou logique de prédicat constitue le principe élémentaire du système de règles : "si condition alors conclusion". La condition est constituée d'une ou de plusieurs prémisses ou encore d'aucune prémisse. ==== Sans prémisse ==== Une règle possédant aucune prémisse est automatiquement éligible. Par exemple, le programme suivant consiste en une règle donnant l'ordre d'avancer à chaque pas. Aucune extension du modèle de base n'est requise. Le type de commande utilisé ici est déjà totalement défini dans le modèle de base //[[nomosdk:bancs_essais#le_modele_de_nomo_de_base|worldsquare.mod]]//. La valeur de sortie //**output **// à 2, correspond à la commande motrice envoyée au composant extérieur gérant l'agent dans le monde dalle. La correspondance entre les items et les valeurs de commandes est représentée uniquement par les règles. Il ne peut y avoir deux règles de commande avec la même conclusion. ... Dans les [[doc:langage_nomo#la_base_de_connaissances|paramètres de la base de connaissances]] //tutorial_1.bas//, le seuil de l'oubli //**timespan**// mis à la valeur //**auto**// conduit par déduction à la valeur 1ms, ce qui signifie que les faits ne restent qu'un pas dans la [[doc:base_de_connaissances#la_base_de_faits|mémoire événementielle]]. Ainsi l'agent évolue dans l'environnement //tutorial_1.map// de la manière suivante: - agent sur la dalle rouge, sélection de la règle M1, envoi de la commande d'avancer, introduction du fait //**advance**// ; - exécution de l'action, agent sur la dalle verte, sélection de la règle M1, envoi de la commande d'avancer, oubli du précédent fait, introduction du fait //**advance**//; - exécution de l'action, agent sur la dalle bleue, sélection de la règle M1, envoi de la commande d'avancer, oubli du précédent fait, introduction du fait //**advance**// ; - échec de l'action motrice, agent sur la dalle bleue, sélection de la règle M1, envoi de la commande d'avancer, oubli du précédent fait, introduction du fait //**advance**// ; - échec de l'action motrice, agent sur la dalle bleue, sélection de la règle M1, envoi de la commande d'avancer, oubli du précédent fait, introduction du fait //**advance**// ; ... La figure suivante correspond au chronogramme du programme, les pointillés signifient //"conduit à"// : {{ :tutorial:fr:tutorial_1_chronogram_1_fr.png?nolink&400 |}} A ce stade, un autre cas peut être facilement illustré, celui où deux règles sélectionnables de même type ont des conditions identiques. La règle choisie correspond alors à la première règle rencontrée dans la base de règles. Par exemple, ajoutons une règle M2 similaire à M1 hormis qu'elle donne l'ordre de tourner à droite. Si la règle M2 est placée à la suite de M1 alors c'est M1 qui sera toujours sélectionnée ; à l'inverse dans le cas où M2 serait placée devant M1, ce serait cette dernière qui alors serait toujours sélectionnée. ==== Avec une prémisse ==== Une prémisse correspond aux critères de reconnaissance d'un événement d'un certain type. Le cas le plus général correspond à une prémisse acceptant tout événement d'un type donné quel que soit le contenu, la crédibilité, ou l'étiquette temporelle ; toutefois pour ce dernier, le signe doit être spécifié. Ici, seul le contenu a une tolérance nulle, les autres situations seront abordées progressivement dans les autres sections. === La perception === Dans l'exemple qui suit, un ensemble de trois règles sert à identifier la teinte des dalles. Ces trois règles sont regroupées dans un schème nommé //**hue_perceptions**//. L'organisation en schème est arbitraire, elle sert uniquement à organiser les règles du point de vue du programmeur. Dans ce cadre, le modèle doit être complété de manière à étendre l'ensemble de définition de la [[doc:langage_nomo#les_structures_perceptives|structure perceptive]] **//hue//** dédiée à la perception de la teinte sur laquelle se trouve l'agent. L'ensemble des items disponible se réduit à //**red**//, //**green**// et //**blue**//. L'élément //**perceptive_structure**// avec le nom //**hue**// dans le modèle //tutorial_1.mod// devient : La tolérance associée à la valeur de la teinte attendue est nulle, c'est à dire que si aucune règle n'identifie exactement la teinte aucune règle de perception n'est déclenchée. La teinte d'une dalle est accessible par un clic gauche sur celle-ci. Dans l'environnement initial, les dalles rouges, vertes, bleues possèdent réciproquement une teinte de 0, 100 et 200. Une dalle avec une autre valeur que celles-ci ne provoquera aucune perception. Le modèle complété, il suffit alors de recopier les règles ci-dessous dans le programme //tutorial_1// : A noter, qu'il ne peut y avoir deux règles de perceptions avec une même conclusion. A ce stade, le déroulement du programme n'affiche aucune différence avec le programme précédent, toutefois l'activité des règles est la suivante : - agent sur la dalle rouge, sélection des règles M1 ainsi que P1, envoi de la commande d'avancer, introduction du fait de commande //**advance**// et du fait de perception //**red**// ; - exécution de l'action, agent sur la dalle verte, sélection de la règle M1 ainsi que P2, envoi de la commande d'avancer, oubli des faits précédents, introduction du fait de commande //**advance**// et du fait de perception //**green**// ; - exécution de l'action, agent sur la dalle bleue, sélection de la règle M1 ainsi que P3, envoi de la commande d'avancer, oubli des faits précédents, introduction du fait de commande //**advance**// et du fait de perception //**blue**// ; - échec de l'action, agent sur la dalle bleue, sélection de la règle M1 ainsi que P3, envoi de la commande d'avancer et faire un son bleu, oubli des faits précédents, introduction du fait de commande //**advance**// et du fait de perception //**blue**// ; ... Soit le chronogramme suivant : {{ :tutorial:fr:tutorial_1_chronogram_2_fr.png?nolink&400 |}} === La perception et l'action=== Afin de rendre compte de la perception, chaque perception peut être associée à un son qui sera symbolisé par un arc évanescent dont la teinte correspond à celle détectée. Dans le modèle de base, le type de commande du son se trouve défini avec la perception du son car il renvoie à des phénomènes considérés de même nature. Dans ce cas, [[doc:langage_nomo#les_structures_perceptives|la structure perceptive]] impose que l'ensemble des perceptions contient l'ensemble des commandes. Dans l'objectif de s'assurer une correspondance avec la perception de la teinte, l'ensemble des items disponibles reprend les valeurs //**red**//, //**green**// et //**bleu**//. L'élément //**perceptive_structure**// avec le nom //**sound**// dans le modèle //tutorial_1.mod// devient : Les règles de commande font le lien entre une perception d'une teinte et la commande d'un son. Ces règles de commande sont regroupées dans un schème nommé //"sound_commands"//. A noter, qu'il ne peut y avoir, comme pour les règles de perception, deux règles de commandes avec une même conclusion. Pour toutes ces règles, l'étiquette temporelle n'étant pas précisée, elle est considérée par défaut comme une valeur positive avec une tolérance infinie. Le calcul du seuil de l'oubli reste donc au minimum, c'est à dire 1ms. La crédibilité n'étant pas définie, elle est par défaut à 1 avec une tolérance infinie. En plaçant ces deux schèmes dans le premier programme comportant uniquement la règle M1 et en repositionnant l'agent en sa position initiale, le déroulement du programme s'effectue de la manière suivante : - agent sur la dalle rouge, sélection des règles M1 ainsi que P1, envoi de la commande d'avancer, introduction du fait de commande //**advance**// et du fait de perception //**red**// ; - exécution de l'action, agent sur la dalle verte, sélection de la règle M1 ainsi que P2 et S1, envoi de la commande d'avancer et faire un son vert, oubli des faits précédents, introduction du fait de commande //**advance**//, //**red**// et du fait de perception //**green**// ; - exécution des actions, __arc rouge__, agent sur la dalle bleue, sélection de la règle M1 ainsi que P3 et S2, envoi de la commande d'avancer et faire un son vert, oubli des faits précédents, introduction du fait de commande //**advance**//, //**green**// et du fait de perception //**blue**// ; - échec de l'action motrice, exécution de l'action sonore, __arc vert__, agent sur la dalle bleue, sélection de la règle M1 ainsi que P3 et S3, envoi de la commande d'avancer et faire un son bleu, oubli des faits précédents, introduction du fait de commande //**advance**//, //**blue**// et du fait de perception //**blue**// ; - échec de l'action motrice, exécution de l'action sonore, __arc bleu__, agent sur la dalle bleue, sélection de la règle M1 ainsi que P3 et S3, envoi de la commande d'avancer et faire un son bleu, oubli des faits précédents, introduction du fait de commande //**advance**//, //**blue**// et du fait de perception //**blue**// ; ... Soit le chronogramme suivant : {{ :tutorial:fr:tutorial_1_chronogram_3_fr.png?nolink&400 |}} ==== Avec plusieurs prémisses ==== Le dernier exemple permet de lier une perception à une action, toutefois la production du signal "sonore" n'est pas synchrone avec la couleur de la dalle sur laquelle se trouve l'agent. Cela est dû au fait que la relation perception/action se décompose au minimum en deux règles alors que l'avance s'effectue à chaque pas de temps. L'exemple suivant vise à synchroniser la production "sonore" et l'avance de l'agent, c'est à dire avancer tout en produisant un arc de même couleur que la dalle que l'agent vient de quitter. La solution proposée utilise la notion de priorité évoquée à la fin du premier exemple et introduit la notion d'opérateur OU et ET. Avec les propriétés plus avancés présentées ultérieurement, des solutions plus élégantes pourront être imaginées. === L'opérateur OU ==== L'opérateur OU se traduit par l'existence de plusieurs règles ayant la même conclusion ; à noter que cet opérateur est interdit pour les perceptions et les commandes afin d'assurer leur intégrité en cas d'apprentissage. Les règles de commandes et de perceptions correspondent aux briques élémentaires qui peuvent servir à la définition de règles de conception représentant une perception ou une commande de plus haut niveau et qui peuvent modéliser l'opérateur OU. Ici, l'emploi de cet opérateur sera illustré avec l'emploi de règles de conception. Mais auparavant, pour synchroniser les règles, un nouveau [[doc:langage_nomo#les_types_de_conception|type de conception]] doit être créé. L'introduction de ce nouveau type se traduit par le rajout dans le modèle //tutorial_1.mod// sous l'élément //**definition**// : L'idée est que la production sonore et l'avance dépendent de l'évènement //**go**// et que la production de cet événement s'effectue en deux temps. Une perception déclenche une règle produisant un évènement //**stop**//, ce dernier conditionnant le déclenchement de l'évènement //**go**//. Les règles servant à la synchronisation sont regroupées dans un nouveau schème : Les règles C1, C2, et C3 expriment un opérateur OU dans le sens où un événement //**stop**// est produit si il y a une perception //**red**// OU //**green**// OU //**blue**//. A noter que la règle C0 est placée en premier dans le schème, de sorte que, en cas d'égale éligibilité avec les autres règles de son type, ce sera elle qui sera sélectionnée. Par ailleurs, il aurait été possible de simplifier ces trois règles en une seule avec une tolérance "INF" comme suit. Autrement dit, la condition de cette règle aurait été remplie quelle que soit la perception établie. Mais dans ce cas, il n'y a pas stricte équivalence car cette seconde solution autorise l'ajout de nouvelles couleurs alors que l'autre oblige l'écriture d'une nouvelle règle le cas échéant. === L'opérateur ET ==== L'opérateur ET consiste à mettre plusieurs prémisses dans une même règle. Ici, ce mécanisme permet de conditionner l'envoi d'une commande de son à une perception donnée ET à l'évènement //**go**//. Le schème //"sound_commands"// devient : Il reste maintenant à modifier la règle M1 qui se déclenchait inconditionnellement à chaque pas de temps, en ajoutant une prémisse concernant l'événement //**go**// : Le déroulement du nouveau programme s'effectue alors selon le chronogramme suivant : {{ :tutorial:fr:tutorial_1_chronogram_4_fr.png?nolink&600 |}} ===== Logique floue ===== La logique floue permet d'évaluer des valeurs non binaires. Par exemple, dans les programmes précédents, les tolérances sont strictement nulles : soit la valeur correspond à celle attendue, soit elle ne correspond pas. Une dalle qui aurait une teinte de valeur 1 ne conduirait à aucune perception alors qu'un rouge de teinte 0 et un rouge de teinte 1 sont très proches. Dans le cadre du formalisme nomo, l'introduction de la logique floue provient de l'évaluation des valeurs continues constituant [[doc:base_de_connaissances#les_evenements_externes|les vecteurs d'entrées]] et [[doc:base_de_connaissances#l_indice_temporel|les indices temporels]] ainsi que [[doc:base_de_connaissances#a_credibilite|les crédibilités]]. L'évaluation de ces valeurs continues s'effectue via [[doc:moteur_inference#l_evaluation_des_regles|un calcul d'une distance]] basé sur un noyau gaussien compris entre 0 et 1 ; 1 si identique, 0 si trop différent. Le résultat de l'évaluation de l'ensemble des prémisses de la règle sélectionnée correspond à la crédibilité associée à l'évènement produit par la conclusion. Le premier exemple concerne l'évaluation de valeurs continues des entrées mais il est transposable aux autres sortes de valeurs continues. Le second exemple aborde l'utilisation de la notion de crédibilité. ==== Les valeurs continues === L'objectif de cet exemple est de rendre l'agent moins sensible à la variation de la teinte. Pour ce faire, une tolérance est rajoutée aux prémisses d'entrée des règles. Dans ce cadre, la tolérance représente l'écart type de la gaussienne caractérisant la prémisse. Seules les règles de perceptions sont modifiées. Autrement dit, le déroulement reste le même sauf que la tolérance aux entrée est plus grande de sorte qu'une perception de vert produit par une entrée vert-jaune conduira à la production d'un arc vert. La tolérance passe ici de 0 à 7. Le changement de la teinte des dalles s'effectue par l’intermédiaire [[nomosdk:bancs_essais#interface_graphique|d'une fenêtre de paramétrage]] qui s'ouvre par un clic sur la dalle ou l'agent concerné. Si une valeur d'entrée est trop éloignée de la moyenne par rapport à l'écart type, le score devient très proche de zéro de sorte qu'il est considéré comme nul lorsqu'il est inférieur à 1,17549E-38. Par exemple, une dalle avec une teinte de 300 correspondant à un rose ne permettra la sélection d'aucune perception. Toutefois, si une perception est toujours souhaitée, une valeur par défaut peut être introduite en ajoutant un nouvel item dans le modèle de perception et en ajoutant une nouvelle règle avec une tolérance infinie. Les zones d'influences des règles perceptions peuvent se traduire par la visualisation des [[doc:moteur_inference#la_selection_des_regles|espérances]], la règle sélectionnée étant celle qui maximise l'espérance. Le graphique suivant représente l’espérance des trois règle de perception en fonction de la teinte, où la couleur des courbes représente la couleur perçue et les droites noires en pointillés la perception P0 : {{ :tutorial:fr:tutorial_1_gausian_1_fr.png?nolink 600 |}} L'environnement de développement [[:nomoSDK]] permet à l'aide de la [[:nomoSDK:macro#la_construction_de_regles_a_partir_d_intervalles|macro de discrétisation]] de déterminer automatiquement les valeurs et les tolérances des règles uniquement en fonction des frontières entre les items. ==== La crédibilité d'un fait ==== Dans ce second exemple dédié à la logique floue, la production d'arc de couleur ne sera plus liée à la couleur perçue mais à la crédibilité avec laquelle elle est perçue. Si la perception est très crédible (proche de 1) alors un arc vert doit être produit, si la crédibilité est moyenne (proche de 0,5), un arc bleu et si elle est proche de zéro, un arc rouge. Dans ce cas, une tolérance infinie est appliquée sur l'information. Précédemment, la crédibilité et l'indice temporel n'apparaissaient pas explicitement dans les règles de sorte que ce sont leurs valeurs par défaut qui étaient appliquées : valeur à un avec une tolérance infinie. L'introduction de la crédibilité dans les prémisses oblige à expliciter également l'indice temporel. Les règles de production des arcs de couleurs deviennent : Le graphique ci-dessous permet de visualiser les zones d'activation des règles de commande en fonction de la crédibilité du fait de perception, les zones colorées indiquent la règle sélectionnée : {{ :tutorial:fr:tutorial_1_gausian_2_fr.png?nolink&500 |}} Dans l’exemple précédent, l'égalité des tolérances implique que toutes les règles possèdent une [[doc:moteur_inference#l_esperance_et_la_specificite|spécificité]] identique de sorte que la règle sélectionnée correspond à celle dont la crédibilité est maximale. Mais ceci correspond à une situation particulière, à une situation d'équilibre. En effet, plus une règle est [[doc:moteur_inference#l_esperance_et_la_specificite|spécialisée]], plus elle devient prioritaire par rapport aux autres règles sur sa zone de sensibilité définie par ses prémisses. Ce qui signifie qu'à crédibilité égale une hiérarchie entre les règles est définie. En modifiant les tolérances des règles de commandes avec respectivement les valeurs 0.361, 0.632, 0.707, les zones d'influences deviennent : {{ :tutorial:fr:tutorial_1_gausian_3_fr.png?nolink&500 |}} ==== La crédibilité et la commande ==== Lorsque le vecteur de sortie associé à la commande est envoyé, la crédibilité l'est également. Le composant extérieur lié à cette commande peut utiliser ou non cette crédibilité. Dans le cadre du [[nomosdk:bancs_essais#le_monde_de_dalles|banc d'essai monde de dalles]], une crédibilité basse (>2/3) conduit à un retard d'un pas et une crédibilité très basse (>1/3) conduit à deux pas de retard. Dans les exemples précédents, la crédibilité des commandes "sonores" était supérieure à 2/3 donc sans retard. Dans l'exemple suivant, la crédibilité de la commande "sonore" dépendra de la crédibilité de la perception en s'appuyant sur la [[doc:moteur_inference#remarque_sur_le_calcul_de_la_distance|remarque sur la propagation des valeurs]] avec une tolérance sur la crédibilité de 0,1775. Seule la perception de rouge conduira à la production d'un arc rouge avec un retard dépendant de l'éloignement de la teinte de la dalle par rapport à un rouge de référence à 0, soit le programme minimal suivant : Si la première dalle possède un rouge de teinte 5 alors la crédibilité de la perception rouge sera de 0,779. La crédibilité de la commande sera alors de 0,871. Dans ce cas, aucun retard ne sera induit. Si la première dalle a un rouge de teinte 10 alors la crédibilité de la perception rouge sera de 0,368. La crédibilité de la commande sera alors de 0,324. Dans ce cas, la production de l'arc s'effectuera donc avec deux pas de retard. Le chronogramme du second cas est alors le suivant : {{ :tutorial:fr:tutorial_1_chronogram_6_fr.png?nolink&350 |}} ===== Logique non-monotone ===== Une logique non-monotone permet que la relation de conséquence ne soit pas nécessairement monotone. Cela signifie qu'ajouter un fait à un ensemble de règles peut empêcher des déductions qui étaient précédemment possibles. On peut considérer que Titi l'oiseau vole tant que l'on ignore qu'il s'agit d'un pingouin. Dans le formalisme nomo, la non-monotonie repose sur deux notions distinctes, la spécificité et l'inhibition. ==== La spécificité ==== La [[doc:moteur_inference#l_esperance_et_la_specificite|spécificité]] définit une hiérarchie entre les règles. Plus une règle est spécifique, plus elle est prioritaire sur les règles générales, et il n'y a qu'une règle sélectionnée par type. L'exemple précédent sur la logique illustrait déjà le rôle de la spécificité mais pas dans le cadre de la non-monotonie qui confronte des règles comportant un nombre de prémisses différent. En revanche, le mécanisme de non-monotonie peut s'illustrer en modifiant le schème //"control"//. En ajoutant une prémisse de la règle //"C0"//, la priorité de la règle ne provient plus de sa position dans le programme mais de sa condition : ... Dans ce cas, la non-monotonie vient du fait que l'évènement de perception //**red**// qui déclenche la règle //"C1"// peut ne pas se produire si l'évènement //**stop**// est également présent à la faveur de la règle //"C0"//. ==== L'inhibition ==== L'inhibition constitue le second moyen pour modéliser de la logique non-monotone. La possibilité d'[[doc:moteur_inference#l_evaluation_des_regles|inhiber une règle]] vient de la présence d'une ou de plusieurs prémisses inhibitrices dont la crédibilité va se soustraire aux prémisses excitatrices. Par rapport à l'[[#avec_plusieurs_premisses|exemple précédent]] dont l'objectif était de produire un arc de la couleur de dalle que l'agent venait de quitter, le mécanisme d'inhibition permet de simplifier les règles ainsi que le modèle et de raccourcir le nombre de pas. En effet, dans une logique purement positive, il était nécessaire d'introduire de nouveau évènement pour synchroniser les règles. Dans une logique d'inhibition, les évènements peuvent également servir de verrou. Ainsi, la fréquence de sélection de la règle motrice peut être divisée par deux en ajoutant une prémisse inhibitrice sur un événement de commande motrice. La règle s'inhibera alors toute seule pendant un pas puis au delà d'un pas le fait commande sera oublié par la mémoire telle qu'elle est configurée. Afin de synchroniser //"M1"// et les règles de production d'arc //"S1"//, //"S2"// et //"S3"// qui dépende d'une perception, une prémisse excitatrice de perception est ajoutée à la condition de la règle : Les règles de production d'arc //"S1"//, //"S2"// et //"S3"// sont alors synchronisées de la même manière que la règle motrice //"M1"// : Avec ce programme, les règles de conception dédiées à la synchronisation ne sont plus utiles ni même le type de conception défini dans le modèle. Le chronogramme devient alors : {{ :tutorial:fr:tutorial_1_chronogram_5_fr.png?nolink&500 |}} ===== Logique temporelle ===== La logique temporelle nécessite une mémoire événementielle pouvant mémoriser plus d'un fait par type d'évènement (//**maximum_of_internal_event**// > 1) et un seuil d'oubli supérieur à la période de l'horloge ici à 500ms (//**time_span_limit**// > 500). Pour les exemples qui suivent, une mémorisation de cinq faits est souhaitée sur une durée strictement inférieure à 3500ms ; toutefois, cinq événements consécutifs donnent une profondeur strictement inférieure à 2500ms. Il faut donc modifier la [[doc:langage_nomo?&#la_base_de_connaissances|configuration par défaut]], soit le fichier //tutorial_1.base// :
...
A noter que ces changements entrainent le dysfonctionnement des programmes précédents où l'indice temporel des prémisses (de catégorie différent d'//**input**//) prend la valeur par défaut un avec une tolérance //"INF"//. En effet, dans ce cas, tous les évènements mémorisés possèdent la même valeur. Pour revenir à un fonctionnement normal, il faut mettre l'indice temporel à 0 avec une tolérance nulle afin de préciser que seuls les évènements venant d'arriver doivent être pris en compte. La logique temporelle dépend de la gestion de la mémoire à laquelle les premiers exemples sont consacrés, suivi des exemples concernant la temporisation ainsi que les horloges, les séries temporelles et, les prédictions. ==== La gestion de la mémoire ==== La mémoire évènementielle correspond à un tore comportant au maximum //**maximum_of_internal_events**// évènements dont l'indice temporel est strictement inférieur à //**time_span_limit**//. Si la mémoire est pleine le nouvel évènement viendra écraser le plus ancien évènement. Pour illustrer la gestion de la mémoire, un programme simple de trois règles pourra être décliné. La règle de commande //"M1"// sert uniquement à rendre concret l'évolution temporelle en faisant avancer l'agent à chaque pas. La règle de commande //"S1"// sert à identifier une situation de la mémoire événementielle du type de conception //"control"//. La règle de conception //"C1"// sert à alimenter la mémoire d'événements. Cette configuration initiale aura un fonctionnement identique quels que soient les paramètres utilisés puisque les prémisses détectent uniquement les évènements venant d'arriver et que le délai à la conclusion de //"C1"// est nul. La règle "C1", produisant des évènements à chaque pas, sature la mémoire au bout du cinquième pas, de sorte que la profondeur réelle de la mémoire est strictement inférieure à 2500ms. Pour tester la profondeur de la mémoire, il suffit de modifier le //**timespan**// de la prémisse de //"S1"//. Si //**timespan**// >= //**time_span_limit**//, cela produira une erreur à la compilation car une prémisse ne peut attendre un indice temporel supérieur ou égal au seuil de l'oubli //**time_span_limit**// défini dans les [[doc:langage_nomo#la_base_de_connaissances|paramètres de la base de connaissances]]. Si //**timespan**// >= 2500ms, la règle //"C1"// ne sera jamais appliquée car les nouveaux évènements écrasent les anciens. Si //**timespan**// multiple de 500ms (puisque //**tolerance** = 0//) est strictement inférieur à 2500ms alors la règle se déclenchera dès qu'un premier évènement acquerra la durée désignée. Elle demeurera sélectionnée à chaque pas puisque le flot d'évènement ne cessera pas de fournir de nouveaux évènements. Si le délai de la conclusion devient supérieur à zéro, dans ce cas la profondeur de la mémoire dépend de la capacité à résorber les délais. Par exemple si le //**delay** = 500ms//, la profondeur est simplement décalée d'autant. Pour tester l'oubli non par l'écrasement d'évènements mais par leur dépassement du seuil, une solution consiste ici à diviser par deux la fréquence de sélection de //"C1"// en introduisant une prémisse inhibitrice. ==== La temporisation et les horloges ==== La temporisation consiste à différer le déclenchement d'une ou de plusieurs règles. L'exemple ci-dessous consiste à différer l'avance de l'agent au lancement du programme. Pour introduire une telle latence, il existe principalement deux solutions. La première consiste à attendre le front d'un flot d'évènements générés à chaque pas : Dans ce cas, il faudra attendre le 2000/500 + 1 pas pour déclencher la règle //"M1"//. Mais cette méthode rend dépendant le programme à la fréquence d'interprétation ainsi que à la profondeur temporelle de la mémoire évènementielle. La seconde méthode utilise la capacité des [[doc:base_de_connaissances#les_regles_de_conception|règles de conception]] à générer des [[doc:base_de_connaissances#les_evenements_internes|évènements intentionnels]], c'est-à-dire des évènements dont l'indice temporel est négatif. Une prémisse de conception discrimine obligatoirement soit les intentions (//**timespan**//<0), soit les évidences (//**timespan**//>=0) ; même lorsque la tolérance est infinie, d'où la nécessité de préciser un hypothétique indice temporel. Contrairement aux évènements passés dont l'indice temporel est borné par le seuil de l'oubli, les évènements intentionnels peuvent arriver avec un indice temporel négatif infini (c'est-à-dire le temps maximal autorisé par l’implémentation). La seconde solution utilise les évènements intentionnels comme un moyen de définir des états. La règle //"C1"//, qui se déclenchera uniquement au premier pas, place un évènement intentionnel dont la durée détermine la latence avant le déclenchement de la règle //"C2"// qui générera une intention permanente autorisant les déclenchements de //"M1"// : Avec ce mécanisme, il devient possible de définir des horloges internes en définissant une règle servant à déclencher une première fois une règle provoquant ensuite périodiquement son propre déclenchement. Les horloges peuvent servir notamment pour synchroniser des règles. Par exemple, une solution pour synchroniser les règles //"S1"//, //"S2"//, //"S3"// et, //"M1"// de [[tutoriel:proprietes_logiques#avec_plusieurs_premisses|l'exemple précédent]] aurait pu être d'introduire une horloge comme suit : À noter que l'ajout de prémisses peut transformer une horloge en "boucle tant que". ==== Les séries temporelles ==== Dans cette section, quatre exemples élémentaires seront présentés afin d'illustrer les détections de séries temporelles d'événements. Tous ces exemples reprendront la règle motrice //"M1"// minimale ainsi que les règles de perception du [[tutoriel:proprietes_logiques#la_perception|second exemple]] de la logique d'ordre 0 soit : Cet ensemble de règles permet à l'agent d'avancer et de percevoir la teinte de la dalle à chaque pas. Dans les exemples qui suivent, l'identification d'une série temporelle conduira à la production d'un arc de couleur bleue par la règle //"S3"//. == Une dalle rouge et une dalle verte == Ce premier exemple définit la condition de la règle //"S3"// comme la détection de deux perceptions de teinte, une rouge et une verte. Dans la condition détectant cet évènement composé, seule la teinte est spécifiée, pour la crédibilité et l'indice temporel, la tolérance est infinie. Toutefois, deux évènements de même type ne peuvent arriver simultanément dans la mémoire, de sorte qu'implicitement les faits de perception de la teinte qui répondront à la condition de //"S3"// seront forcément séparés dans le temps. Dans l’environnement initial, la dalle rouge et la dalle verte se suivent de sorte que, une fois la dalle verte parcourue, l'agent produira un arc bleu tant qu'il existe au moins un fait //**red**// ET au moins un fait //**vert**// dans la mémoire évènementielle, autrement dit //**maximum_of_internal_events**// - 1 pas. Soit le chronogramme suivant : {{ :tutorial:fr:tutorial_1_chronogram_7_fr.png?nolink&400 |}} Mais la condition de //"S3"// n'oblige pas la juxtaposition des faits ni un ordre particulier de perception de sorte que dans l'environnement suivant : {{ :tutorial:tutorial_1_map_2.png?nolink&300 |}} Le chronogramme devient : {{ :tutorial:fr:tutorial_1_chronogram_8_fr.png?nolink&400 |}} == Une dalle rouge puis une dalle verte == Dans le cas où l'ordre des faits serait important et que la détection doit s'effectuer uniquement lors de l'apparition des faits, alors la condition de la règle //"S3"// devient : == Une dalle rouge puis de suite une dalle verte == Si, par rapport à la règle précédemment définie, il est souhaité que les faits se suivent de suite alors, il suffit de mettre l'indice temporel de la prémisse capturant le fait //**red**// à la valeur correspondant au délai séparant les deux faits, soit ici 500ms. == Une dalle rouge puis plus ou moins de suite une dalle verte == Une tolérance non nulle sur l'indice temporel permet de détecter des séries temporelles avec une certaine variabilité sur le temps. Par exemple, la règle //"S3"// ci-dessous se déclenche lorsque le fait //**green**// apparaît juste après le fait //**red**// ou au pas suivant. En effet, au delà du pas suivant, le score de //"S3"// devient inférieur à 1,17549E-38 et par conséquent il est considéré comme nul. A noter que, dans le cas où plusieurs évènements pourraient correspondre à une ou plusieurs prémisses, la configuration choisie est celle qui maximise le score de la règle. ==== Les prédictions ==== Une prédiction définit un délai et un contenu ainsi qu'une évaluation dont la satisfaction dépend de la tolérance associée à ce délai et à la crédibilité de ce contenu. Le formalisme nomo modélise les [[doc:base_de_connaissances#les_regles_de_prediction|prédictions]] via une [[doc:langage_nomo#les_structures_predictives|structure prédictive]] constituée de trois règles de trois types différents : //**prediction**//, //**landmark**// et //**check**//. Les règle de type //**landmark**// et de type //**prediction**// possèdent une condition identique. La règle de type //**landmark**// génère un évènement qui servira de point de comparaison avec l'évènement de prédiction généré par la règle de type //**prediction**// dans le cadre de l'évaluation de la règle de type //**check**// qui contrôle à la fois le contenu et le temps de l'évènement prédit. Les prédictions portent uniquement sur les perceptions et les conceptions. Au sein du modèle //"tutorial_1"//, la structure prédictive concernant la perception //"hue"// est la suivante avec l'ajout de l'élément //**predicted_by**// dans la structure perceptive: Dans l'exemple qui suit, le programme vise à prévoir une dalle rouge si l'agent perçoit une dalle verte. Dans le cas d'une avance à chaque, la prédiction stipule que la perception du rouge s'effectuera après 1500ms soit l'avance de trois cases. L'introduction de la prémisse inhibitrice permet d'éviter la production d'évènements qui perturberaient la prédiction en cours. Toutefois, pour un même type, chaque prédiction différente est évaluée successivement et, une prédiction à plus court terme interrompra la prédiction en cours. La fin de l'évaluation forcée ou normale conduit à la production d'un évènement //**check**// dont la crédibilité indique la qualité de la prédiction, aux extrêmes : 0 prédiction totalement incorrecte, 1 prédiction parfaite. La visualisation de la réussite ou de l'échec de la prédiction pourra se faire en modifiant les règles //**S1**// et //**S2**// via la crédibilité de l'évènement de contrôle //**check**// : Avec cette dernière configuration de l'environnement, le chronogramme de prédiction est le suivant, en fond vert la durée de l'évaluation de la prédiction, (1500 + 50 x 1) / 500 = 3,1 arrondi au supérieur cela donne 4 pas : {{ :tutorial:fr:tutorial_1_chronogram_9_fr.png?nolink&700 |}} ===== Logique révisable ===== Une logique révisable permet de défaire un état ou un fait que l'on croyait acquis. En d'autres termes, cela revient à introduire la notion d'état ou de verrou. Dans le formalisme nomo ce mécanisme peut être modélisé via les évènements intentionnels. En effet, l'arrivée d'une nouvelle intention élimine toutes celles dont le terme vient après cette dernière. Par exemple, on souhaite rajouter à l'agent une variable interne mémorisant s'il a déjà perçu dernièrement une dalle rouge ou bleue. Pour cela un nouveau type de conception appelé //remember// comprenant deux items complète le modèle : Le schème "management_remember" qui permet de mettre en place ou défaire un état //red// ou //bleu//. Lorsque l'agent est activé, aucune intention //remember// n'est présente. Dès que l'agent perçoit une teinte de la dalle, la règle sélectionnée correspond soit //"RR1"// soit //"RB1"//. Ces règles produisent un évènement sans délai de sorte que toutes les précédentes intentions sont éliminées. Elles autorisent ensuite la production d'évènements intentionnels avec un délai maximal via respectivement //"RR2"// et //"RB2"//. L'état //bleu// ou //red// est représenté à la fois par un événement avec un indice temporel nul et par un évènement intentionnel.