Académique Documents
Professionnel Documents
Culture Documents
Préface
Introduction
Classe de NewsArticle
Classe de FilterAgent
Discussion
Résumé
Exercices
Introduction
Dans cette section, nous présentons une introduction aux deux matières principales couvertes
dans ce livre : intelligence artificielle et agents intelligents. Nous traçons l'histoire de la
recherche en matière d'intelligence artificielle et discutons les lieux de base des écoles de
traitement de symbole et de réseau neurologique. Nous explorons l'évolution des systèmes
d'intelligence artificielle d'une technologie intéressante mais en grande partie critiquée dans la
base pour des applications d'aujourd'hui d'agent intelligent. L'apparition simultanée du calcul
de réseau et du World Wide Web, et leurs conditions pour le logiciel intelligent sont
également discutées. Nous présentons les attributs principaux des agents intelligents tels que
l'autonomie, la mobilité, et l'intelligence et fournissons une taxonomie pour classifier de
diverses applications d'agent intelligent.
Intelligence artificielle
Cependant, les succès tôt ont été suivis d'une réalisation lente que ce qui était dure pour des
personnes et facile pour des ordinateurs était plus qu'a compensé par les choses il était facile
pour des personnes faire que mais presque impossible pour que les ordinateurs fassent. La
promesse des premières années jamais n'a été entièrement réalisée, et la recherche d'AI et
l'intelligence artificielle de limite sont devenues associées à l'échec et à la technologie
overhyped.
Concepts de base
Dans toute son histoire, l'intelligence artificielle s'est concentrée sur les problèmes qui se
trouvent juste au delà de la portée de quels ordinateurs du dernier cri pourraient faire à ce
moment-là (riches et chevalier 1991). En tant que systèmes de l'informatique et informatiques
se sont transformés en des niveaux plus élevés de la fonctionnalité, les secteurs qui tombent
dans le domaine de la recherche d'AI ont également changé. Inventé pour calculer des
diagrammes de balistique pour des armes d'II-ère de guerre mondiale, la puissance et la
polyvalence des ordinateurs juste étaient imaginés. Les calculateurs numériques Étaient un
concept relativement nouveau, et les idées de ce qui serait jeu et mathématiques inclus par
fonctions utiles de jeu d'AI.
Après 40 ans de travail, nous pouvons identifier trois phases importantes du développement
dans la recherche d'AI. En premières années, une grande partie du travail a traité les
problèmes formels qui ont été structurés et a eu des frontières bien définies de problème. Ce
travail inclus sur des qualifications math-connexes telles que prouver des théorèmes, la
géométrie, le calcul, et jouer des jeux tels que des contrôleurs et des échecs. Dans cette
première phase, l'emphase était sur créer la « pensée générale usine » qui serait capable de
résoudre de grandes catégories de problèmes. Ces systèmes ont tendu à inclure le
raisonnement sophistiqué et à rechercher des techniques.
Une deuxième phase a commencé par l'identification que les projets d'AI les plus réussis
étaient des domaines très étroits visés de problème et a habituellement codé beaucoup de
connaissance spécifique au sujet du problème à résoudre. Cette approche d'ajouter la
connaissance spécifique de domaine à un système plus général de raisonnement a mené au
premier succès commercial dans des systèmes d'AI-expert. Des systèmes experts basés sur les
règles ont été développés pour faire de diverses tâches comprenant l'analyse chimique, les
systèmes informatiques de configuration, et diagnostiquer des conditions médicales dans les
patients. Ils ont utilisé la recherche dans la représentation de connaissance, ingénierie
cognitive, et ont avancé des techniques de raisonnement, et ont montré que l'intelligence
artificielle pourrait fournir la valeur réelle dans des applications commerciales. À ce même
temps, des postes de travail d'ordinateur ont été développés spécifiquement pour fonctionner
des applications blèsent, de Prolog, et de causerie. Ces postes de travail d'AI ont comporté les
environnements de développement integrated puissants et étaient des années en avant d'autres
environnements de logiciel commerciaux.
Nous sommes maintenant bien dans une troisième phase des applications d'AI. Depuis les fin
des années 1980, une grande partie de la communauté d'AI avait travaillé à résoudre les
problèmes difficiles de la vision par ordinateur et la parole, l'arrangement et la traduction de
langage naturel, le raisonnement commonsense, et la commande de robot. Une branche d'AI
connue sous le nom de connexionisme a regagné la popularité et a augmenté la gamme des
LY_SII __ 7 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Traitement de symbole
Le comportement intelligent peut être produit par la manipulation des symboles. C'est l'un des
principes primaires des techniques d'intelligence artificielle. Les symboles sont des marques
qui représentent les objets ou les idées réels et peuvent être représentées à l'intérieur d'un
ordinateur par des chaînes de caractères ou par des nombres. Dans cette approche, un
problème doit être représenté par une collection de symboles, et alors un algorithme approprié
doit être développé pour traiter ces symboles.
L'hypothèse physique de systèmes de symbole (Newell et Simon 1980) indique que seulement
« un système physique de symbole a les moyens nécessaires et suffisants pour l'action
intelligente générale. » Cette idée, cette intelligence découle de la manipulation active des
symboles, était la pierre angulaire sur laquelle une grande partie de la recherche suivante d'AI
a été établie. Les chercheurs ont construit les systèmes intelligents using des symboles pour la
reconnaissance des structures, raisonnement, apprenant, et prévoyant (Russell et Norvig
1995). L'histoire a prouvé que les symboles peuvent être appropriés pour le raisonnement et la
planification, mais que la reconnaissance des structures et l'étude peuvent mieux être laissées
à d'autres approches.
LY_SII __ 8 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Il y a plusieurs manières typiques de manoeuvrer les symboles qui ont prouvé utile en
résolvant des problèmes. Le plus commun est d'employer les symboles dans les formulations
de si alors les règles qui sont traitées using des techniques de raisonnement appelaient
l'enchaînement vers l'avant et en arrière. L'enchaînement vers l'avant laisse le système déduire
la nouvelle information d'un ensemble donné de données d'entrée. L'enchaînement en arrière
permet au système de tirer des conclusions basées sur un état de but spécifique. Une autre
technique de traitement de symbole est un réseau sémantique, dans lequel les symboles et les
concepts qu'ils représentent sont reliés par des liens dans un réseau de la connaissance qui
peut alors être employé pour déterminer de nouveaux rapports. Un autre formalisme est une
armature, où des attributs relatifs d'un concept sont groupés ensemble dans une structure avec
des fentes et sont traités par un ensemble de procédures relatives appelées des démons ou les
remplisseurs. Le changement de la valeur d'une fente simple pourrait placer outre d'un ordre
complexe des procédures relatives pendant que l'ensemble de la connaissance représenté par
les armatures est rendu conformé. Ces techniques de raisonnement sont décrites en plus détail
en chapitres 3 et 4.
Réseaux neurologiques
Une méthode de plus en plus populaire en intelligence artificielle s'appelle les réseaux
neurologiques ou le connexionisme. Les réseaux neurologiques ont moins à faire avec le
traitement de symbole inspiré par la logique mathématique formelle, et plus pour faire avec la
façon dont l'intelligence humaine ou normale se produit. Les humains ont les réseaux
neurologiques dans des leurs têtes, se composant des centaines de milliards de cellules du
cerveau appelées les neurones, reliés par les synapses adaptatives qui agissent en tant que
systèmes de commutation entre les neurones. Des réseaux neurologiques artificiels sont basés
sur cette architecture massivement parallèle trouvée dans le cerveau. Ils l'information de
processus, pas par des symboles de manipulation, mais en traitant des grands nombres de
données brutes d'une façon parallèle. Différentes formulations des réseaux neurologiques sont
employées pour segmenter ou des données de faisceau, pour classifier des données, et pour
faire les modèles prédictifs using des données. Une collection d'unités de traitement qui
imitent les fonctionnements de base de vrais neurones est employée pour remplir ces
fonctions. Pendant que le réseau neurologique apprend ou est formé, un ensemble de poids de
raccordement entre les unités de traitement est modifié a basé sur les rapports perçus dans les
données.
Comparé aux systèmes de traitement de symbole, les réseaux neurologiques remplissent des
fonctions cognitives relativement de bas niveau. Les connaissances qu'ils acquièrent par
l'apprentissage sont stockées dans les poids de raccordement et ne sont pas facilement
disponibles pour l'examen ou la manipulation. Cependant, la capacité des réseaux
neurologiques d'apprendre de et s'adapter à leurs environnements est une fonction cruciale
requise par les systèmes logiciels intelligents. D'une perspective de la science cognitive, les
LY_SII __ 9 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Là où la recherche en matière d'intelligence artificielle a été par le passé dominée par des
techniques de traitement de symbole, il y a maintenant une vue plus équilibrée où les forces
des réseaux neurologiques sont employées pour parer les faiblesses du traitement de symbole.
Dans notre vue, tous les deux sont absolument nécessaires afin de créer des applications
intelligentes et des agents autonomes intelligents.
L'Internet s'est développé hors du placement de gouvernement pour les chercheurs qui ont dû
collaborer au-dessus de grandes distances. Comme sous-produit de résoudre ces problèmes,
des protocoles qui ont permis à différents ordinateurs de parler entre eux, les données
d'échange, et le travail ensemble requis ont été développés. Ceci a mené au TCP/IP comme
protocole de gestion de réseau de norme de fait pour l'Internet. La croissance de l'Internet est
stupéfiante, avec le nombre d'emplacements s'élevant exponentiellement. Des milliers de
nouveaux emplacements sont reliés à l'Internet chaque mois.
Tandis que le courrier électronique (email) était par le passé le service primaire fourni par
l'Internet, l'édition de l'information et la distribution de logiciel sont maintenant d'importance
égale. Le service d'information des textes de Gopher, qui a gagné la popularité au début des
années 90 a produit de la première vague d'information éditant sur le filet. Le File Transfer
Protocol permet à des utilisateurs de télécharger des travaux de recherche et les articles aussi
bien que recherchent des actualisations de logiciel et accomplissent même des logiciels au-
dessus de l'Internet. Mais c'était le protocole de transfert hypertexte (HTTP) qui a introduit
l'Internet du royaume du milieu universitaire et des technologues informaticiens dans la
conscience publique. Le développement du navigateur de mosaïque à l'Université des Illinois
a transformé l'Internet en support de communications d'usage universel, où les novices et les
experts en matière d'ordinateur, les consommateurs, et les entreprises peuvent agir l'un sur
l'autre des manières entièrement nouvelles.
souscrivent aux emplacements qui envoient les mises à jour constantes à leurs pages Web,
cette condition pour filtrer l'information ne partira pas. À moins que les emplacements
d'émission puissent envoyer les jets très personnalisés d'information, l'utilisateur devra encore
séparer l'information valable du bruit inutile.
Tandis que l'Internet et le World Wide Web ont attiré l'attention de public, les entreprises
adaptent rapidement la manière qu'elles emploient la technologie de l'information par leurs
réseaux internes ou intranets. Intranets d'utilisation de compagnies pour l'email interne et
externe, pour signaler l'information, et pour gérer des tâches administratives courantes. Les
Intranets permettent à une large variété d'ordinateurs de client de se relier aux serveurs
centralisés, sans coût et complexité des applications se développantes de client/serveur. Les
Intranets atteignent le même objectif et ont les mêmes avantages pour les compagnies que
l'Internet a pour des individus. Une application de client normalisée, le web browser, courant
sur les PCs standard ou les ordinateurs de réseau peu coûteux, peuvent fournir un unique de
l'accès à une collection d'applications network-based de corporatewide.
De même que souvent le cas quand un champ technique provoque l'intérêt commercial, il y a
eu un grands mouvement et changement de foyer de la communauté de la recherche d'AI pour
s'appliquer les techniques de base d'intelligence artificielle aux systèmes informatiques
répartis, aux intranets d'entreprise, à l'Internet, et au World Wide Web. Au commencement, le
foyer a été limité pour exprimer les tâches de recherches, de recherche documentaire, et de
filtrage. Mais car de plus en plus des transactions commerciales sont effectuées sur des
réseaux, il y a plus d'intérêt en ayant des agents futés qui peuvent effectuer des actions
spécifiques. En rapportant une étape et en regardant ce qu'est devenu l'Internet, beaucoup de
chercheurs qui avaient regardé comment les agents intelligents pourraient coopérer à réaliser
des tâches sur les systèmes informatiques répartis se sont rendus compte qu'il y a finalement
un problème à la recherche d'une technologie (par opposition à l'autre manière autour). Les
agents intelligents peuvent fournir la valeur réelle aux utilisateurs en ce monde nouveau, relié
ensemble, et géré en réseau.
Jusqu'à ce point, nous avons discuté l'intelligence artificielle et son évolution dans des agents
de logiciel à un niveau abstrait. Dans les sections suivantes, nous explorons certaines des
facettes techniques des agents intelligents, comment ils fonctionnent, et comment nous
pouvons les classifier avons basé sur leurs capacités et technologies fondamentales.
Événement-Condition-Actions
Supposer que nous avons un agent intelligent, fonctionnant de façon autonome, amorcé avec
la connaissance au sujet des tâches que nous exigeons de elle et préparons pour sortir sur le
réseau quand l'occasion se présente. Maintenant ce qui ? Comment l'agent sait-il que nous
voulons qu'il fasse quelque chose pour nous, ou qu'elle devrait répondre à quelqu'un qui
essaye de nous contacter ? C'est où nous devons traiter des événements, identifier des
conditions, et agir.
Dans le cadre des agents intelligents, un événement est quelque chose qui s'avère justement
changer l'environnement ou n'importe quoi dont l'agent devrait se rendre compte. Par
exemple, un événement a pu être l'arrivée d'un nouveau morceau de courrier. Ou c'a pu être un
LY_SII __ 11 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
changement à une page Web. Ou ce pourrait être un temporisateur allant au loin au minuit-
temps de commencer à envoyer les fax qui sont alignés vers le haut. Court de avoir notre
agent constamment exploiter et vérifier ou voter tous les systèmes de dispositif et
informatiques nous voulons qu'il surveille, ayant le signal d'événements les occurrences
qu'importantes soit la prochaine meilleure chose. En fait, ce peut être la meilleure chose, parce
que notre agent peut dormir, pensent au sujet de ce qui s'est produite pendant le jour, font des
tâches de ménage, ou toute autre chose utiles tandis qu'il attend le prochain événement pour se
produire.
Quand un événement se produit, l'agent doit identifier et évaluer ce que signifie l'événement
et puis répond à lui. Cette deuxième étape, déterminant ce que l'état ou l'état du monde est,
pourrait être simple ou extrêmement complexe selon la situation. Si le courrier est arrivé, alors
l'événement individu-décrira-un le nouveau morceau de courrier est arrivé. L'agent peut alors
devoir questionner le système de courrier pour découvrir qui a envoyé le courrier, et ce qui est
le sujet ou matière, ou même balayer le texte de courrier pour trouver des mots-clés. Toute la
ceci fait partie du composant de reconnaissance du cycle. L'événement initial peut réveiller
l'agent, mais l'agent alors doit figurer dehors ce qu'est la signification de l'événement dans la
limite de ses fonctions. Dans l'exemple de courrier, supposer que l'agent identifie que le
courrier est de votre patron, et que le message est classifié comme PRESSANT. Ceci nous
amène à prochain et peut-être la plupart utile d'aspect des agent-actions intelligentes.
Si les agents intelligents vont rendre nos vies plus faciles (ou au moins plus intéressantes),
elles doivent pouvoir agir, pour faire des choses pour nous. En ayant des ordinateurs faire les
choses pour nous n'est pas une nouvelle idée. Des ordinateurs ont été développés pour aider
des personnes travaillent. Cependant, ayant l'initié d'ordinateur une action en notre nom est
quelque chose totalement différente de sélectionner une commande sur la ligne de commande
et en pressant entrer pour courir la commande. Tandis que les résultats de notre introduire la
commande et du pressurage entrent ne peut pas toujours être exactement ce que nous avons eu
à l'esprit quand nous l'avons saisi (il semble toujours que nous réalisons que ce que nous
devrions avoir dactylographié après que nous pressions entrer), nous savons que celui qui se
produise, il est notre faire. En ayant un agent (intelligent ou pas, humain ou automatisé)
prendre une mesure pour nous exige un certain saut de la foi ou au moins un certain niveau de
confiance. Nous devons espérer que notre agent intelligent va se comporter rationnellement et
dans notre meilleur intérêt. Comme toutes les situations où nous déléguons la responsabilité à
un tiers, nous devons peser les risques et les récompenses. Le risque est que l'agent salira des
choses vers le haut, et nous devrons effectuer encore plus le travail pour placer des choses
droites. La récompense est que nous sommes libérés de devoir s'inquiéter des détails d'obtenir
ce morceau de travail fait.
Tandis que les agents intelligents sont toujours quelque peu nouveaux dans les
environnements de calcul commerciaux, ils ont été le centre des chercheurs pendant des
années. Dans ce temps, on a proposé beaucoup de différentes manières de classifier ou de
classer des agents par catégorie. L'one-way est de placer l'agent dans le cadre de l'intelligence,
de l'agence, et de la mobilité. Une autre approche est de se concentrer sur la stratégie de
traitement primaire de l'agent. Un tiers est de classer l'agent par la fonction qu'il remplit. Dans
les sections suivantes nous explorons chacune des trois perspectives sur des possibilités
d'agent de visionnement.
Quand nous parlons des agents de logiciel, il y a trois dimensions ou haches que nous
employons pour mesurer les possibilités : agence, intelligence, et mobilité (IBM 1996).
L'agence traite le degré d'autonomie que l'agent de logiciel a en représentant l'utilisateur à
d'autres agents, d'applications, et de systèmes informatiques. Un agent représente l'utilisateur,
aide l'utilisateur, guide l'utilisateur, et dans certains cas, prend des mesures unilatérales au
nom de l'utilisateur. Cette progression d'aide simple au véritable aide nous prend des agents
qui peuvent être hardcoded, à ceux, qui hors de la nécessité simple, doivent contenir des
techniques plus avancées d'intelligence.
Un agent est mobile s'il peut se déplacer entre les systèmes dans un réseau. La mobilité
présente la complexité additionnelle à un agent intelligent, parce qu'elle soulève des
inquiétudes concernant la sécurité (l'agent et le système de cible) et le coût. Les Intranets sont
un environnement particulièrement mûr pour que les agents intelligents mobiles errent parce
qu'ils exigent moins de sécurité que dans l'Internet grand -ouvert.
Stratégies de traitement
Un des types les plus simples d'agents sont des agents réactifs ou réflexes, qui répondent en
mode d'événement-condition-action. Les agents réflexes n'ont pas les modèles internes du
monde. Ils répondent seulement aux stimulus externes et aux informations disponibles de leur
détection de l'environnement (ruisseaux 1986). Comme les réseaux neurologiques, les agents
réactifs montrent le comportement émergent, qui est le résultat des interactions de ces
différents agents simples. Quand les agents réactifs agissent l'un sur l'autre, ils partagent des
données de bas niveau, la connaissance symbolique non à niveau élevé. Un des principes
fondamentaux des agents réactifs est qu'ils sont fondus dans des données physiques de sonde
et ne fonctionnent pas dans l'espace artificiel de symbole. Des applications de ces agents ont
été limitées aux robots qui utilisent des sondes pour percevoir le monde.
LY_SII __ 13 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Comme cité précédemment, un agent mobile est un processus de logiciel (le code et son état
d'un programme courant) qui peut voyager à travers les systèmes informatiques dans un
réseau effectuant le travail pour son propriétaire. Un avantage des agents mobiles est que les
communications entre le système à la maison et les systèmes à distance sont réduites. En
permettant à l'agent d'aller au système à distance et aux données d'accès localement sur ce
système, nous permettons une nouvelle classe entière des applications. Par exemple, les
agents mobiles ont pu fournir une manière simple de faire l'équilibrage de la charge dans les
systèmes distribués. « Oh, le processeur est fortement chargé ici, un meilleur houblon dessus
plus d'au système X pendant un moment. »
Comme Nwana (1996) dit, la « mobilité n'est ni un état nécessaire ni suffisant pour
l'agenthood. » Parfois elle semble raisonnable de faire sortir à votre agent sur le réseau ;
d'autres fois elle ne fait pas. Pour certains, l'idée d'envoyer un agent mobile au travail est
éteinte confortable et normale. Pour d'autres, le manque d'un modèle de calcul familier (il ni
serveur-n'est basé ni client/serveur) rend les agents mobiles durs pour sonder. Par exemple, si
votre agent contient la quelques connaissance ou algorithmes exclusifs de domaine, puis
envoyant que la propriété intellectuelle dehors sur le réseau à résider sur les centres serveurs
étrangers, peut ne pas être une bonne idée. Améliorer pour maintenir cet agent à la maison
dans un système sûr et bloqué, et envoyer les agents de collaboration de messager pour faire
le déplacement. Peut-être le plus grand inhibiteur à l'utilisation répandue des agents mobiles
est sécurité. Nous avons un nom pour le logiciel qui vient unbidden sur nos systèmes et
commence à s'exécuter. Nous les appelons des virus. Comment nous assurons-nous que
seulement les « bons » agents mobiles peuvent fonctionner sur notre système, mais pas les
« mauvais » agents ? Et comment pouvons-nous faire la différence ?
Fonctions de traitement
Peut-être la façon de penser la plus normale au sujet des différents types d'agents est basée sur
la fonction qu'elles remplissent. Ainsi, nous avons des agents d'interface utilisateurs, qui
LY_SII __ 14 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
essayent « font ce que voulez dire vous que » plutôt que ce que vous dites en agissant l'un sur
l'autre avec un morceau d'application ou de logiciel système. Nous avons des agents de
recherche, qui sortent sur l'Internet et trouvent des documents pour nous. Nous avons des
agents de filtre, qui traitent le courrier entrant ou les articles de discussion, ferreting dehors la
substance d'intérêt des déchets plus mondains ou plus inintéressants. Nous avons des aides
domain-specific, qui peuvent réserver un voyage d'affaires, prévoir une réunion, ou vérifier
que notre conception ne viole aucune contrainte. En bref, n'importe quelle combinaison des
attributs d'agent intelligent peut être combinée et appliquée à un domaine spécifique pour
créer un nouveau, fonction-spécifique agent intelligent. Tous que nous devons sont les outils
logiciels et l'infrastructure de calcul pouvoir ajouter les possibilités de la connaissance et de
raisonnement ou d'étude de domaine à nos agents, et le niveau de confort qui est exigé de faire
confiance à l'agent pour faire notre offre.
Les agents d'interface fonctionnent comme les aides personnels pour aider un utilisateur à
accomplir des tâches. Les agents d'interface utilisent habituellement l'étude pour s'adapter aux
habitudes de travail et aux préférences de l'utilisateur. Patti Maes (1994) au MIT identifie
quatre manières que l'étude peut se produire. D'abord, un agent peut apprendre par
l'observation au-dessus de l'épaule de l'utilisateur, observant ce que l'utilisateur fait et imitant
l'utilisateur. En second lieu, l'agent peut offrir le conseil ou agir au nom de l'utilisateur et puis
apprendre en recevant la rétroaction ou le renfort de l'utilisateur. Troisièmement, l'agent peut
obtenir des instructions explicites de l'utilisateur (quand ceci se produit, puis font cela). En
conclusion, en demandant d'autres agents le conseil, et l'agent peut apprendre de leurs
expériences. Noter que les agents d'interface collaborent principalement avec l'utilisateur, pas
avec d'autres agents (demander le conseil est l'une exception). Using de diverses mécanismes
d'apprentissage, connecter l'offre d'agents la promesse d'adapter l'interface utilisateurs d'un
système informatique ou l'ensemble de demandes d'utilisateur particulier et de leur travail
unique dénomment. Si les agents d'interface peuvent collaborer et partager leur connaissance
au sujet de la façon faire une tâche, alors quand une personne dans une équipe de travail
figure dehors comment faire quelque chose, que la compétence pourrait être transmissible à
tous autres utilisateurs dans cette équipe de travail par leurs agents d'interface. Les gains de
productivité ont pu être énormes.
Une autre classe générique des agents est des agents de l'information. Par certains côtés, les
agents de l'information sont le Dr. Jekyll/M. Hyde des logiciels. Quelques agents de
l'information sortent sur l'Internet ou le Web et cherchent l'information d'intérêt à l'utilisateur.
D'autres filtrent des jets d'information venant dans des signalisations de correspondance et de
newsgroup d'email. Mais l'une ou l'autre manière, agents de l'information essayent d'aider
avec le problème de noyau d'obtenir la bonne information au bon moment. La question n'est
pas s'il y a trop d'information ou trop peu, mais veillant que vous voyez la bonne information.
Naturellement, ce qui est « exact » dépend du contexte dans lequel vous travaillez. Ce
problème de surcharge de l'information est l'un des facteurs principaux dans l'apparition des
agents intelligents de logiciel en tant que produits commercial viables. Si conduisant en
particulier les messages électroniques importants, ou activement construisant un journal
personnel (consistant seulement en articles et annonces intéressants), le soulagement de
promesse d'agents de l'information de la quantité primordialement de données nous sont
exposés à chaque jour. Des agents de l'information appelés Spiders déjà sont employés pour
indexer le Web. Généralement les agents de l'information peuvent être statiques, et se
reposent sur un système using des moteurs de recherche et des index de Web pour recueillir
des informations pour l'utilisateur, ou ils peuvent être mobiles et sortir et activement
LY_SII __ 15 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
rechercher l'information. L'une ou l'autre manière, leur fonction demeure même-à fournissent
l'information utile à l'utilisateur.
Dans les sections précédentes, nous avons décrit trois des taxonomies principales pour
classifier des agents, mais il y a d'autres. Certains estiment que la collaboration avec d'autres
agents est une distinction importante. D'autres estiment que, que l'agent agisse l'un sur l'autre
directement avec un utilisateur humain ou pas est important. Encore d'autres jugent que cela la
capacité d'étude devrait servir de base primaire à classifier des agents. Si l'agent fonctionne à
travers un réseau ou seulement localement sur un PC ou un poste de travail est un autre
attribut de distinction. Puisque les agents intelligents existent dans un espace
multidimensionnel, la caractérisation des agents par deux ou de trois de ces dimensions est
quelque peu risquée (Nwana 1996). Cependant, nous estimons que la perte de précision est
plus qu'avons compensé par la clarté des deux ou approche tridimensionnelle. Les gens ont du
mal à penser dans les six ou sept-dimensionnels espaces. À notre avis, l'agence et
l'intelligence sont les possibilités fondamentales fondamentales sur lesquelles des agents
devraient être classifiés. La mobilité ou certaine autre caractéristique a pu être employée
comme troisième axe, au besoin.
Pour être sûr, il y a des agents de logiciel qui sont autonomes, mais de non intelligent. Ces
agents agissent souvent en tant que moniteurs d'exécution de machine simple dans des
applications de gestion de système distribué. Les agents de Simple Network Management
Protocol sont un exemple de cette sorte. D'une part, il y a des programmes ou des applications
qui emploient les techniques d'intelligence artificielle telles que l'étude et des motifs, mais qui
avoir relativement peu d'autonomie. Les systèmes experts classiques sont un exemple. Ils ne
sont pas les agents intelligents dans le sens utilisé dans ce livre. Nous sommes intéressés par
les programmes à l'intersection de deux domaines, intelligences et agences. Toutes autres
caractéristiques sont secondaires et des mai ou mai pour ne pas être présentes pour que nous
emploient l'agent intelligent de limite.
Les agents intelligents sont des logiciels, rien plus et rien moins. Parfois ceci a un impact
négatif quand quelqu'un nouveau à la matière vient à la réalisation qu'il n'y a aucune magie
ici, juste programmant. Cependant, les agents intelligents, du moins car nous les définissons et
nous référons, sont des logiciels avec une attitude. Ils existent pour aider des utilisateurs à
obtenir leur travail effectué. Vous pouvez dire qu'est ce ce que le logiciel d'application est
censé pour faire. C'est vrai. Cependant, beaucoup d'applications assument aujourd'hui un
niveau de connaissance et de sophistication dans les utilisateurs que beaucoup d'utilisateurs
sont incapables ou peu disposés à réaliser. Les gens veulent juste obtenir leur travail réalisé.
Les la plupart ne s'inquiètent pas si la police est TrueType ou Adobe, si le modèle composant
est ActiveX ou JavaBeans, ou si le code est client/serveur ou basé sur le WEB. Vers cette
extrémité, le logiciel d'agent intelligent est logiciel pratique. Il obtient juste le travail réalisé.
Si le logiciel d'agent intelligent présente un autre niveau de complexité lequel l'utilisateur doit
traiter, alors ce sera un échec. Les agents intelligents doivent être permettants et
automatisants, non frustrant ou intrusif.
Résumé
En ce chapitre, nous avons présenté une introduction à l'intelligence artificielle et aux agents
intelligents. Les points principaux incluent :
LY_SII __ 16 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Chapitre 1
À l'origine les réalisateurs de Java ont prévu pour employer C++ pour leur développement de
logiciel. Mais ils ont eu besoin d'une langue qui pourrait s'exécuter sur différents ensembles
de puces pour adapter au marché toujours changeant d'électronique grand public. Ainsi ils ont
décidé de concevoir leur propre langue qui serait indépendant du matériel fondamental.
C'est cet aspect « architecture-neutre » de Java qui lui fait l'idéal pour programmer sur
l'Internet. Il permet à un utilisateur de recevoir le logiciel d'un système à distance et de
l'exécuter sur un système local, indépendamment du matériel fondamental ou du système
d'exploitation. Un interprète et un temps d'exécution s'appellent la machine virtuelle de Java
qui isole le logiciel du matériel fondamental.
À la différence des langues plus traditionnelles, le code source de Java n'obtient pas traduit en
instructions de machine pour une plate-forme particulière d'ordinateur. Au lieu de cela, le
code source de Java (.java) est compilé dans une forme intermédiaire appelée les bytecodes
qui sont stockés dans un dossier de .class. Ces bytecodes peuvent être exécutés sur n'importe
quel système informatique qui met en application une machine virtuelle de Java. Cette
portabilité est peut-être l'un des dispositifs les plus irrésistibles de la langue de Java, d'une
LY_SII __ 18 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Le portable, nature interprétée de Java effectue son exécution. Tandis que l'exécution du code
interprété de Java est meilleure que des langues scripting et assez rapide pour des applications
interactives, elle est plus lente que les langues traditionnelles dont le code source est compilé
directement dans le code machine pour une machine particulière. Pour améliorer l'exécution,
des compilateurs juste à temps (JITs) ont été développés. Un compilateur de JIT fonctionne en
même temps que la machine virtuelle de Java et détermine quels morceaux de code de Java
s'appellent le plus souvent. Ceux-ci sont compilés en marche dans des instructions de machine
de sorte qu'ils n'aient pas besoin d'être interprété chaque fois eux soient produits dans le cadre
d'un programme. Des compilateurs statiques également sont développés pour compiler le code
source de Java dans le code machine qui peut être exécuté sans interprétation. Il est important
de noter que, à la différence des bytecodes, le code machine produit n'est pas portable et ne
s'exécutera pas sur d'autres plates-formes.
La portabilité de bytecode est ce qui permet à Java d'être transporté à travers un réseau et
d'être exécuté sur n'importe quel système informatique de cible. Les Java applets Sont de
petits programmes de Java conçus pour être inclus dans un document de Web de HTML
(langage de balisage hypertexte). Les étiquettes de HTML spécifient le nom du Java applet Et
de son localisateur de ressources uniformes. L'URL est l'endroit sur l'Internet auquel les
bytecodes d'applet résident. Quand un web browser Java-permis affiche un document de
HTML contenant une étiquette d'applet, les bytecodes de Java sont téléchargés de l'endroit
spécifique et la machine virtuelle de Java interprète ou exécute les bytecodes. Les Java applets
Sont ce qui permettent à des pages Web de contenir les graphiques animated et le contenu
interactif.
Puisque des Java applets Peuvent être téléchargés de n'importe quel système, les mécanismes
de sécurité existent dans la machine virtuelle de Java pour se protéger contre les applet
malveillants ou errants. Le système d'exécution de Java vérifie que les bytecodes pendant
qu'ils sont téléchargés du réseau pour s'assurer ils sont les bytecodes valides et que le code ne
viole pas des restrictions inhérentes l'unes des imposées aux applet. Les Java applets Sont
restreints de la communication avec n'importe quel serveur autre que le centre serveur de
commencement, celui dont ils ont été téléchargés. Ils ne peuvent pas lancer un programme
exécutable local ou accéder aux dossiers locaux. Les restrictions sont in place pour empêcher
un Java applet D'accéder au du système d'exploitation fondamental ou des données sur le
système. Ces restrictions peuvent être soulagées, cependant, par l'utilisation des signatures
digitales et des réalisations alternatives de SecurityManager.
Mais Java peut être employé pour plus que les applet de programmation pour courir chez un
navigateur. Java est un langage de programmation de plein exercice qui peut être employé
pour écrire des applications autonomes. Ces applications ne sont pas placées sous les mêmes
restrictions de sécurité que les applet et peuvent donc accéder à des données et à la fonction
du système d'exploitation fondamentale.
Java est assez semblable à C et à C++ qu'il se sent déjà bien connu à la majeure partie de la
communauté de programmation existante. Mais il est assez différent des manières importantes
(gestion de la mémoire principale et portabilité de croix-plate-forme) ces il le vaut pour que
les programmeurs commutent à une nouvelle langue.
Cette section n'inclut pas les pleines spécifications de langue pour Java mais est prévue pour
fournir assez d'informations pour que le C.A. ou le programmeur de C++ obtienne une
sensation pour Java. Pour une description complète de la langue, voir le site Web de JavaSoft
chez http://www.javasoft.com/.
Types de données
Bien que Java soit un langage de type objet, les types de données primitifs ne sont pas des
objets. Des objets équivalents sont fournis en tant qu'élément de la langue, mais les primitifs
permettent une exécution plus rapide en éliminant l'associé aérien aux objets. Le tableau 1.1
décrit les types de données primitifs (de non-Objet) disponibles dans Java.
Les déclarations variables sont semblables à ceux dans C ou C++. Java est un langage opérant
sur des objets de types déterminés fortement, ainsi chaque variable doit avoir un type. Le type
peut être un type de données primitif, ou un type de données de référence. Les données
primitives dactylographient dedans Java sont passées par valeur. Ceci signifie que la valeur
réelle est stockée dans une variable, et la valeur elle-même est passée aux appels de méthode.
Les objets, d'une part, sont des types de données de référence. Ceci signifie que la variable
contient une référence à l'adresse à laquelle l'objet est stocké, et la référence est passée aux
appels de méthodes. Des variables dans Java peuvent être initialisées une fois avouées et
peuvent être déclarées à un point quelconque dans le code. Voici quelques exemples des
déclarations variables dans Java :
boolean flag;
char answer = ‘N’;
int[] arrayOfIntegers = new int[10];
String myName;
Comme vu dans l'exemple ci-dessus, les rangées sont les objets de première classe dans Java,
et, comme d'autres objets, doivent être explicitement créées using le nouvel opérateur.
LY_SII __ 20 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Structures de gestion
int i = 0;
while ( i < 10) {
if ( i == 0) {
... // first time
} else {
int j = 0 ;
do {
... // all other times
j++ ;
} while ( j < 10) ;
i++ ;
}
Java soutient la coupure et continue des rapports pour l'éclatement de joindre des boucles et
des rapports de commutateur. Mais Java ajoute une torsion à ces fonctions. Vous pouvez
ajouter une étiquette à une boucle en ajoutant l'étiquette et des deux points avant les
spécifications de boucle. Ceci te permet de spécifier hors de quelle boucle enfermante vous
voulez se casser ou continuer.
Java est un langage de programmation orientée objectivement. Ainsi, la manière que vous
obtenez des choses faites est en définissant des classes, des objets de instanciation, et appeler
des méthodes sur ces objets. Une classe est une collecte des données (appelés les membres) et
méthodes (des fonctions ou des procédures) qui manoeuvrent ces données. Un objet est un
exemple d'une classe et nous employons le terme l'un pour l'autre. Dans Java, il n'y a aucune
variable globale ou fonction ; tout doit être défini en tant qu'élément d'une classe. Au-dessous
de nous définissons une classe de Java simple appelée Agent :
String name ;
Agent contact ;
public String getName() { return name ;}
public Agent getContact() { return contact; }
Agent(String aName) { name = aName; ) ;
}
Dans cet exemple, le nom et le contact sont des membres et le getName () et le getContact ()
sont des méthodes. L'agent (aName de corde) est un constructeur qui est habitué pour créer
un exemple d'agent avec le membre nommé initialisé à la valeur de l'aName. Un objet peut
être créé dans Java suivre le nouveau mot-clé (plus terrain communal) ou la méthode de
newInstance () sur la classe. Par exemple :
Agent msmart,jbond;
msmart = new Agent(“Maxwell”);
jbond = Agent newInstance();
Ici l'agent est une classe, et le msmart et le jbond sont des variables qui mettent en référence
ou se rapportent à des exemples d'agent. Se rappeler, Java n'a aucun indicateur qui peut être
manoeuvré (et probablement abusé). Les variables tiennent les types de données ou les
références élémentaires d'objet, qui sont toujours valides. Noter qu'avant que la deuxième
ligne soit exécutée, le msmart variable ne se rapporte à aucun objet et a une valeur spéciale
appelée nulle. Une référence nulle causera une exception (erreur) si vous essayez de
l'employer pour se référer à un objet.
Nous pouvons obtenir et placer des membres de données dans l'objet l'un ou l'autre
directement, si les permissions d'objet laissent, ou indirectement par des méthodes, encore si
les permissions laissent. Le public, les privés, et des mots-clés protégés détermine si d'autres
objets peuvent accéder à des méthodes de membre ou d'appel de données sur un objet. Par
exemple, nous pourrions obtenir le nom du jbond en codant jbond.name pour accéder au nom
directement, ou en employant l'appel jbond.getName de méthode ().
Dans notre classe d'agent, le nom et le contact s'appellent les variables d'exemple. Chaque
exemple d'un agent aura son propre nom et contacte des membres de données. Nous pouvons
créer les variables de classe, qui s'appliquent à tous les exemples d'agent en employant le
mot-clé statique.
Java ne soutient pas la transmission multiple, où une classe peut être dérivée de deux parents
ou plus ou classes basses. Au lieu de cela, il présente la notion d'une interface. Une interface
est un ensemble de méthodes qui définissent un comportement spécifique qui est soutenu par
un exemple de la classe. Par certains côtés, la construction d'interface est plus puissante que la
transmission multiple, parce qu'elle permet à n'importe quelle classe d'imiter le comportement
d'autres classes sans souci de leurs membres de données ou stratégies d'exécution
fondamentaux. La causerie permet seulement la transmission simple, mais n'a rien comme la
construction d'interface de Java. C++ permet la transmission multiple, mais la complexité
rend using elle sujet aux erreurs. L'interface de Java semble comme un compromis
raisonnable entre ces deux approches.
LY_SII __ 22 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Applet et applications
Le code de Java peut être couru comme seules applications de stand ou comme applet, qui
sont courus dans un navigateur en tant qu'élément d'une page Web. Commençons par des
applications parce qu'ils sont les plus familiers. N'importe quelle classe de Java peut être
transformée en application en fournissant () à une méthode principale la signature suivante :
Une application de Java peut être appelée de la ligne de commande en spécifiant le mot-clé
Java suivi du nom de la classe : Java AgentApp. Se rappeler que Java est une langue
interprétée, ainsi nous ont besoin d'un autre programme pour lire et interpréter les bytecodes
dans l'AgentApp.class classent. C'est le temps d'exécution de Java, dans le dossier exécutable
Java. Tous les paramètres ont passé dedans sur la ligne de commande peuvent être accédés
par la rangée de corde d'args, tout comme le paramètre d'argv dans le C.A. ou la force de C++
().
Afin de fonctionner comme applet, une classe doit être une sous-classe de la classe d'applet.
Un applet est conçu pour fonctionner sous la commande d'un autre programme,
habituellement un web browser, et se sert de la fenêtre de navigateur pour se montrer et pour
agir l'un sur l'autre avec l'utilisateur. La méthode d'init () est employée aux paramètres de
processus et fait d'autres initialisations ci-devant pour l'applet. Le début () et des méthodes
d'arrêt () s'appellent toutes les fois que l'utilisateur évoque ou laisse la page Web. Un applet
témoin est montré ci-dessous :
Puisque le web browser appelle réellement l'applet, nous avons besoin d'un dossier de HTML
qui met en référence l'applet et spécifie ses paramètres, comme :
LY_SII __ 23 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Le temps d'exécution de Java fournit une visionneuse d'applet qui peut être employée pour
courir des applet en tant qu'applications autonomes. La visionneuse d'applet joue le rôle du
navigateur dans ce cas-ci. Les applet devraient également appliquer le getAppletInfo () et des
méthodes de getParameterInfo () pour fournir des informations sur l'applet et ses paramètres
aux utilisateurs.
Les applet sont l'une des raisons principales que les gens se réfèrent à Java comme langage de
programmation d'Internet. Puisqu'ils ont été employés la première fois pour épicer vers le haut
les pages Web mates avec le texte et les graphiques animated, les Java applets Sont le
dispositif le plus bien connu de la langue de Java. Des applet maintenant sont employés pour
créer les panneaux dynamiques de saisie de données pour des applications navigateur-basées
d'Internet. Ils ont également émergé comme technologie principale derrière le développement
des ordinateurs de réseau en tant que remplacements possibles pour les terminaux non-
intelligents.
L'interface indigène de Java fournit une technique standard pour que Java exige à d'autres
environnements de langue et pour que la machine virtuelle de Java soit appelée des
programmes écrits en d'autres langues. Un d'usage courant de JNI est de fournir des méthodes
indigènes ou des « emballages » de Java pour des api existants de C ou de C++. Ceci permet à
des programmeurs de Java de traiter ces api en tant que prolongements simples à
l'environnement de Java. Mais ce qui se produit réellement sous les couvertures est que la
commande de transferts de JVM dans l'autre environnement de langue (une bibliothèque
partagée de DLL ou d'UNIX) et des passages un indicateur à l'environnement courant de Java.
Quand un programme de Java appelle une méthode indigène, les paramètres (l'un ou l'autre
types de données primitifs tels que l'international, long, ou le flotteur, ou les références aux
objets de Java) sont passées dans la fonction de C ou de C++ api. La méthode indigène peut
alors employer l'indicateur d'environnement de Java et un ensemble de fonctions de JNI pour
appeler des méthodes sur ces objets de Java. Ainsi, un appel de méthode de Java est
transformé en ensemble de paramètres et la fonction fondamentale de C ou de C++ api
s'appelle. Les résultats d'api sont alors retournés à l'environnement de Java, directement ou
par des méthodes appelées pour placer des membres de données sur des objets de Java. Le JNI
fournit également une interface de sorte que le C.A. ou le programme de C++ puisse
commencer vers le haut le JVM et le faire lancer charger et un programme de Java.
LY_SII __ 24 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Un dispositif intéressant de Java est qu'il emploie le jeu de caractères de 16 bits d'Unicode,
plutôt que le codage sur 8 bits d'ASCII. Unicode définit plus de 34.000 caractères codés
couvrant les langues écrites principales de partout dans le monde. Ces possibilités intégrées de
soutien de langue nationale, combinées avec une partie du lieu () ou de traitement sensible
d'endroit présenté dans Java 1.1, signifient que des Java applets Pourraient être écrits pour une
assistance mondiale.
Puisque le temps d'exécution de Java soutient les fils multiples de la commande, les
spécifications de langue incluent un rapport synchronisé qui peut être employé pour marquer
les sections critiques du code pour empêcher la corruption des objets. Le filetage est un
dispositif important pour des applications de calcul de réseau, parce qu'il permet à des
programmes de serveur d'entretenir les clients multiples en tournant de nouveaux fils pour
chaque demande. Cette approche donne une exécution bien meilleure que commençant un
nouveau processus (comme des programmes de CGI-BIN) quand une demande entre.
Paquets
Des ensembles de classes relatives sont groupés ensemble dans des paquets de Java. De la
même manière des cartes d'un nom de classe de Java aux dossiers identiquement appelés de la
source (.java) et de la classe (.class), paquets de Java sont tracées aux annuaires identiquement
appelés. Tous les dossiers de .class qui font partie d'un paquet doivent résider dans le même
annuaire. Un paquet tel que java.awt.image trace à une structure d'annuaire de
Java/d'awt/d'image.
Java soutient grouper des collections de paquets et de classes de Java dans des dossiers de
fermeture éclair dans le format non comprimé. Un nouveau format de empaquetage appelé
JAR (archives de Java) peut également être employé pour grouper des collections de paquets
de Java dans un dossier simple de sorte qu'un ensemble complet de classes de Java puisse être
téléchargé d'un web server dans une transaction simple.
java.lang
Le paquet de java.lang contient les classes de langue de base de Java. Celles-ci incluent des
classes pour des objets et se classent (l'objet, la classe), quelques types de données de base
(booléens, byte, caractère, double, flotteur, nombre entier, long, maths, nombre, short,
corde, StringBuffer, vide), sécurité (SecurityManager), fils (fil, ThreadGroup), et une
autre classe connexe à la compilation et au temps d'exécution de Java. Noter que ces classes
définissent seulement le comportement très essentiel des classes dans la langue de Java. Des
classes plus complexes et plus puissantes basées sur les classes dans java.lang existent en
d'autres paquets. Le paquet de java.lang inclut également l'interface de Cloneable qui est
employée pour indiquer si un objet peut être copié, et l'interface praticable qui indique qu'une
classe devrait être exécutée par un fil.
Ceci le seul paquet qui est automatiquement importé dans chaque programme de Java. La
classe d'objets est la racine de toutes les hiérarchies de classe. Puisque chaque autre objet de
Java est une sous-classe d'objet, tous les objets peuvent appeler le public et les méthodes
protégées de classe d'objets. Ceux-ci incluent des essais pour l'égalité, la synchronisation de
LY_SII __ 25 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
fil sur des objets, la génération de code de gâchis, et l'identification de la classe à laquelle un
objet appartient. Certaines de ces méthodes devraient être dépassées dans les sous-classes
pour fournir les comportements appropriés. Un objet de classe représente une classe de Java
et peut fournir les informations sur la classe elle-même comprenant le nom de classe, les
superclass de la classe, et les interfaces mises en application par la classe.
La majorité du type de données classes sont assez explicite. Les classes de corde et de
StringBuffer sont d'un certain intérêt parce que les objets de corde dans Java sont
immuables, ainsi il signifie que les cordes ont des valeurs constantes qui ne peuvent pas être
changé une fois elles sont définies. Des objets de StringBuffer sont employés pour des
valeurs de corde modifiables.
java.lang.reflect
Le paquet de java.lang.reflect inclut des classes pour soutenir l'introspection au sujet des
classes et des objets fonctionnant actuellement dans une machine virtuelle de Java. Ceux-ci
incluent des classes pour créer et accéder à des rangées (rangée) et pour fournir des
informations et pour accéder aux classes, aux constructeurs, aux champs, aux méthodes, et
aux modificateurs (classe, constructeur, champ, méthode, modificateur). Noter que les
méthodes de réflexion de soutiens de classe mais est réellement une partie de java.lang pour
la compatibilité ascendante avec des versions antérieures de Java.
java.io
Le paquet de java.io contient un grand nombre de classes, plus dont sont descendus
d'InputStream ou d'OutputStream. Les classes de jet définissent des méthodes pour des
données de lecture et d'écriture d'une série de jets. En plus de l'entrée-sortie de jet, java.io
inclut des classes pour l'entrée-sortie de dossier et le filtrage de nom de fichier (dossier,
FilenameFilter, RandomAccessFile). Le paquet de java.io inclut également un certain
nombre d'interfaces. Deux des interfaces plus intéressantes sont Serializable et
Externalizable. L'interface de Serializable permet à un objet d'écrire son état à un jet et de le
relire encore. C'est utile pour passer des objets car des paramètres dans une architecture
distribuée (comme le RMI) et pour rendre un état d'objet persistant. L'interface
d'Externalizable est également employée pour couler des objets, mais l'applicateur a plus de
contrôle du format et du contenu du jet.
java.util
Le paquet de java.util contient plusieurs des structures de données utilisées généralement dans
des programmes d'application. Ceux-ci incluent des classes et des interfaces pour la
LY_SII __ 26 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Les classes et les interfaces d'avis peuvent être employées pour mettre en application le
modèle de conception d'observateur (gamma et autres, 1995), le plus familier dont est le
paradigme de modèle/vue. Un objet observable est un dont les changements doivent être
observés par d'autres objets dans une application. Objets qui souhaitent être annoncés quand
les changements observables d'objet doivent mettre en application l'interface d'observateur
et doivent s'enregistrer avec l'objet observable.
La classe de propriétés laisse des paires de clef/valeur à lire de et être écrit à un jet. Des
objets de propriétés peuvent être employés pour rechercher des valeurs personnalisables
basées sur une clef, semblable aux variables d'environnement dans beaucoup de logiciels
d'exploitation. Si une application doit être courue dans différents lieux, des propriétés peuvent
être chargées dans un PropertiesResourceBundle, qui est une sous-classe de
ResourceBundle. La classe de ResourceBundle contiennent les objets lieu-spécifiques qui
peuvent être chargés comme appropriés pour le lieu courant. Ceci permet à une application
d'être écrit l'indépendant du lieu de l'utilisateur. Ces classes sont très utiles en écrivant le code
qui peut être téléchargé du Web et être exécuté n'importe où dans le monde. Les classes de
ResourceBundle et de lieu, avec des classes dans le paquet de java.text, fournissent l'appui
de l'internationalisation de Java.
java.util.zip
java.net
Le paquet de java.net fournit un ensemble de classes pour des communications à travers des
réseaux. Ceci inclut des classes pour travailler avec des adresses d'Internet et des localisateurs
de ressources uniformes (INetAddress, URL, URLConnection, URLEncoder,
URLStreamHandler, et URLStreamHandlerFactory) et des douilles (douille,
ServerSocket, DatagramSocket, SocketImpl, et SocketImplFactory) aussi bien que des
données (ContentHandler, ContentHandlerFactory, DatagramPacket). Ces classes
permettent à des programmes de Java de fonctionner à n'importe lequel de trois niveaux
logiques au-dessus des réseaux, à l'URL lu un niveau de HTML page, aux douilles crues de
niveau, et au niveau encore plus bas de datagramme. Ces puissance et flexibilité n'est pas le
foyer réseau-central de Java donné étonnant.
LY_SII __ 27 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
java.awt
La trousse à outils abstraite de fenêtrage est un cadre orienté objectivement pour créer les
interfaces utilisateurs graphiques dans Java. Elle fournit des classes pour les composants de
base de fenêtre, pour des graphiques de schéma, et pour automatiquement arranger et remettre
à la côte des composants. À la différence de C et de C++, qui n'ont pas adressé des fonctions
de GUI, Java fournit ce paquet standard de sorte que les Java applets et les applications
Puissent fonctionner sur les logiciels d'exploitation multiples avec l'appui fondamental très
différent de GUI et aller voir raisonnablement commun et se sentir.
Le paquet de java.awt est tout à fait grand avec plus de 100 classes et interfaces dans les
paquets bas d'awt, de java.awt.event, de java.awt.image, et de java.awt.datatransfer. Le
paquet d'awt soutient la plupart des commandes standard de GUI (fenêtre, panneau,
dialogue, vue, toile, ScrollBar, menu, MenuBar, MenuItem, bouton, Checkbox, choix
(listboxes), étiquette, TextField, et TextArea). L'appui de graphiques inclut (police,
FontMetrics, graphiques, image, point, polygone, et rectangle).
java.applet
Le paquet de Java applet Contient une classe simple, l'applet, qui est une sous-classe
d'awt.Panneau, et trois interfaces, l'AppletContext, AppletStub, et AudioClip.
L'AppletContext définit l'environnement que l'applet fonctionne dedans, le document de
HTML il a été chargé de, et d'autres applet dans ce document. L'AppletContext fournit une
manière pour qu'un applet obtienne des références à d'autres applet sur la même page Web, et
d'agit l'un sur l'autre avec eux. L'AppletStub est l'interface entre l'applet et le navigateur ou le
téléspectateur d'applet. Des applet ont été discutés dans une première section sur des applet et
des applications.
java.text
Le soutien d'internationalisation des applet et des applications est fourni par le paquet de
java.text. Ce paquet contient des classes et des interfaces pour traiter le texte d'une manière
lieu-spécifique. Des classes sont données pour des dates, des décimales, des messages, et des
nombres de formatage d'une manière dont se conforme aux conventions de langue locales
(ChoiceFormat, DateFormat, DateFormatSymbols, DecimalFormat,
DecimalFormatSymbols, FieldPosition, format, MessageFormat, NumberFormat,
ParsePosition, SimpleDateFormat). Des interfaces et les classes sont également données
pour assembler et réitérer au-dessus des cordes internationalisées des textes (BreakIterator,
CharacterIterator, CollationElementIterator, CollationKey, assembleuse,
RuleBasedCollator, StringCharacterIterator).
LY_SII __ 28 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
java.security
La sécurité est un souci important avec des applications d'Internet et Java fournit l'appui
architectural intégré pour l'applet et la sécurité d'application. Le paquet de java.security
soutient les applet et les dossiers signés de FIOLE (archives de Java), le chiffrage principal, et
les listes de contrôle d'accès. La classe de sécurité contrôle de soi-disant fournisseurs de
sécurité et centralise toutes les fonctions liées à la sécurité. Un fournisseur de sécurité est
une exécution appelée de certains ou de tous les api de sécurité de Java. Le fournisseur de The
Sun est le défaut et met en application l'algorithme de chiffrage d'architecture de signature
digitale.
java.beans
« Un haricot de Java est un composant de logiciel réutilisable qui peut être manoeuvré
visuellement dans un outil de constructeur » (JavaSoft 1996). Chaque haricot fournit à des
ensembles de propriétés, de méthodes, et d'événements pour l'interaction d'autres haricots.
Introspection de soutien d'haricots, qui permet aux générateurs d'application visuels d'analyser
comment chaque haricot travaille, et personnalisation, de sorte que le comportement de
l'haricot puisse être prolongé dans un environnement visuel de constructeur. Une fois qu'un
haricot est adapté et combiné aux besoins du client avec d'autres haricots dans une
application, elle soutient la persistance, de sorte qu'elle puisse être sauvée et reconstituée plus
tard.
JavaBeans interactif par un modèle d'événement sophistiqué qui comporte les objets
d'EventSource qui peuvent mettre le feu aux événements et aux objets d'EventListener qui
peuvent recevoir ces événements. Par l'introspection, les haricots peuvent déterminer quels
événements d'autres haricots peuvent se produire ou écouter. Il y a un enregistrement
d'événement qui permet à des haricots de changer dynamiquement leurs rôles comme
générateurs ou auditeurs d'événement. Des objets d'EventAdapter peuvent être insérés entre
une source d'événement et un auditeur d'événement pour filtrer des événements, événements
de file d'attente, ou pour agir en tant que « standard » centralisé pour des communications
d'inter-Haricot.
java.rmi
Le paquet de java.rmi est employé pour créer des applications réparties ou des applet d'objet
dans Java. L'invocation à distance de méthode emploie un substitut ou un moignon local pour
contrôler l'invocation des méthodes sur un objet à distance. N'importe quel objet qui peut être
accédé à distance doit mettre en application l'interface à distance. Un objet de nomination
LY_SII __ 29 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
fournit le mécanisme initial de circuit fermé pour obtenir des références à distance d'objet. En
outre, on fournit un RMISecurityManager qui définit la politique de sécurité pour des
moignons dans des applications réparties.
java.sql
Le paquet de java.sql est mieux connu comme JDBC (connectivité de base de données de
Java). Ce paquet permet l'accès aux bases de données de Java et est basé sur le X/Open SQL
CLI. On fournit une classe de DriverManager qui est responsable de charger l'exécution
correcte de conducteur pour une base de données donnée et créera un raccordement à une
base de données particulière. Une exécution de conducteur pour des bases de données
d'ODBC est fournie en tant qu'élément du JDK, et d'autres fournisseurs de base de données
fournissent des conducteurs pour leurs réalisations particulières de base de données. Des
interfaces sont données pour exécuter des commandes SQL Contre une base de données
(CallableStatement, PreparedStatement, rapport), et pour renvoyer les résultats des
questions de base de données (ResultSet). Des classes sont également données pour les types
de données de SQL (date, temps, horodateur, types). En outre, l'appui est fourni pour
questionner la base de données et le conducteur fondamentaux de base de données pour
découvrir quels dispositifs sont soutenus (DatabaseMetaData, DriverPropertyInfo,
ResultSetMetaData). Le résultat global est un paquet qui permet au code de Java d'accéder à
des données dans différentes bases de données de différents fournisseurs employant une
interface de programmation commune.
La condition minimum est d'obtenir le kit de développement de Sun Java, qui fournit une
ligne de commande compilateur de Java, un programme de mise au point rudimentaire, et une
exécution basse de la machine virtuelle de Java. Cependant, la plupart des réalisateurs sont
accoutumés à employer les environnements de développement integrated qui comportent des
constructeurs de GUI, l'élimination des imperfections de code source, gestion des projets pour
la commande de code source, et des navigateurs et des rédacteurs de code source. Inclure le
plus également les compilateurs de JIT pour une meilleure exécution. Il y a plusieurs
compagnies qui vendent des environnements de développement integrated pour Java. Ceux-ci
incluent Symantec, avec son ensemble de produits de Café, Sun avec ses outils d'atelier de
Java, IBM avec son VisualAge pour Java, et Microsoft, avec son instrument de
développement de J++. La beauté de Java et de son interface portative de machine virtuelle
est qu'elle n'importe pas vraiment que le fournisseur ou vous usinent choisissent de
LY_SII __ 30 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
développer vos applications et agents de Java. Tant que vous employez les classes qui font
partie de la langue standard et des utilités, il pourra courir sur n'importe quelle autre plate-
forme. Une note d'avertissement est que Microsoft a présenté les éléments de propriété
industrielle dans ses outils et exécution de Java. Faire attention que vous ne comptez pas sur
ces dispositifs, ou vous serez limité aux plates-formes de Microsoft Windows.
Comme programmeur expérimenté de C++, de tout que j'avais eu connaissance de Java, j'ai
compris que la programmation dans Java ne serait aucune affaire. Après plusieurs jours du
codage, je peux confirmer que Java est un environnement de programmation confortable et
très productif. Pour donner une petite meilleure perspective sur d'où je viens, me laisser
décrivent brièvement mon expérience de C++. J'ai conçu et écrit plusieurs instruments de
développement dans C++ using le GUI de Star Division, Inc. StarView classer les
bibliothèques (pour OS/2, Windows 3.1, et AIX) aussi bien que les bibliothèques de classe
d'IBM OpenClass (également connu sous le nom d'ICLUI). J'ai également employé les
bibliothèques calibre-basées standard de classe de collection qui sont maintenant norme dans
le monde de C++. Ainsi, voici quelques commentaires de novice de Java d'un programmeur
expérimenté de C++ :
Défaut de la reproduction sonore ! L'inscription du nouveau code dans Java me rappelle des
jours plus tôt using les produits de Turbo Pascal. J'emploie l'environnement de développement
de Symantec Café qui est gentil, mais non exceptionnel de quelque façon. Ce qui
m'impressionne plus est la puissance basse des classes de langue et d'utilité de Java. Il en a
pris s'habituant pour moi à ne pas esquisser dehors mes classes dans des dossiers d'en-tête et
créer alors des moignons de méthode dans un cpp classer. Dans Java vous devez définir les
méthodes à l'intérieur de la définition de classe (à moins que vous employez des interfaces,
qui est quelque chose que nous obtiendrons plus tard). Un autre problème que j'ai frappé était
que j'ai voulu faire tous de mon public de classes d'aide, mais Java ne me laissera pas. Elles
toutes doivent être dans les dossiers séparés de .java. Puisque j'étais juste prototypage une
partie du code d'AI, j'ai voulu employer juste un dossier de programme. J'ai fait ceci en
rendant toute les aide des classes non publiques. Une fois que j'écris plus de code, je retirerai
les objets communs dans leurs propres classes.
Que m'impressionne au sujet de Java ? La classe de vecteur semble être une classe
extrêmement utilisable de liste qui peut tenir des objets de n'importe quel type et qui peut être
employée comme file d'attente. J'aime particulièrement l'interface d'énumération qui dirigent
(et d'autres classes) l'appui. Avec ceci vous pouvez faire une boucle de moment () avec
list.hasMoreElements () et list.nextElement (). Je ne peux pas te dire combien d'heures elle a
pris pour obtenir à ma première classe calibre-basée par C++ pour compiler et lier. C'était une
brise.
Une autre chose que j'ai dû faire était d'analyser un certain texte. Dans C j'emploierais la
fonction de strtok (), avec laquelle n'est pas joli pour travailler. À IBM OpenClass
j'emploierais un IString avec une interface de mot (). Dans Java, j'ai employé un
StringTokenizer qui soutient l'interface d'énumération. L'analyse d'une corde dans des
marques était aussi facile que les hasMoreElements d'un moment () () et la boucle de
LY_SII __ 31 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
J'ai eu quelques problèmes avec le Java « tout est que paradigme d'une référence » pour des
objets. Quand je code une classe dans C++, je peux spécifier que des objets sont contenus ou
mis en référence. C++ sait assez pour appeler le constructeur de défaut pour les membres de
données qui sont contenus (pas des indicateurs aux exemples). Mais puisque Java n'a aucune
notion des indicateurs, tous les membres de données sont implicitement « par la référence. »
Ceci signifie qu'à moins que vous fassiez un nouveau classXYZ () dans votre constructeur, la
première fois que vous essayiez de mettre en référence tous les objets de membre de données,
vous obtiendrez une exception de pointeur nul.
Un autre « dispositif » non-ainsi-évident de Java est les classes immuables d'emballage pour
les types de données primitifs. Vous pouvez coder des choses comme international, flotter, et
doubler juste comme dans C ou C++. Java fournit avec bonté le nombre entier, le flotteur, et
les doubles classes ainsi vous pouvez transformer ces valeurs en véritables objets de Java. Le
seul problème est qu'ils sont immuables (ils ne peuvent pas être changé une fois eux sont
créés). J'ai essayé de passer un nombre entier dans une méthode et de l'employer comme
variable de rendement. Mais cela n'a pas fonctionné parce que je ne pourrais pas le changer.
Une méthode de setValue () sur la classe d'emballage sure serait gentille.
Dans les sections précédentes de ce chapitre, nous avons décrit les éléments principaux du
langage de programmation de Java. Dans cette section, nous parlons des dispositifs
spécifiques de Java qui soutiennent des applications d'agent intelligent. Ces dispositifs seront
explorés en plus détail dans le reste du livre.
qui a été libéré au mid-1991. C'était l'un des premiers produits d'IBM embarqués qui a été
écrit dans la causerie. Plus récemment, j'ai employé IBM VisualAge pour que la causerie crée
une interface de prototype aux api de NNU V3. Ceci a renforcé ma perception que la causerie
est un environnement de programmation supérieur à C++ et également convaincu me que la
programmation visuelle pourrait être extrêmement productive. Plus tôt, j'ai dit que je
n'attendais pas beaucoup de Java, une fois comparé à la causerie. C'est parce que Java se
fonde sur la syntaxe de C++, qui est encore plus mauvaise que le C. Mais je sais que Java
objet-est basé (ignorer ces international et types de flotteur pour le moment) et qu'il a la
collection d'ordures au lieu de ces méthodes merveilleuses nouvelles/suppression dans C++.
Une fois que vous apprenez l'ordre de causerie de la priorité (unaire, binaire, message) pour
l'évaluation d'expression, c'est la manière la plus normale de penser au code d'OO, ainsi je ne
pourrais pas image ce que Java pourrait offrir.
Bien, après utilisation de Java je peux dire qu'il a quelques choses gentilles. Le premier dont
est que le code est compréhensible pour des programmeurs de C et de C++ (tristement,
causerie en prend qui s'habitue). J'ai également trouvé la hiérarchie de classe pour être moins
complexe et plus franc pour employer que les classes traditionnelles de causerie.
Tandis que Java pourrait regarder plutôt C++, il pense (se sent et agit) plutôt la causerie.
J'aime pouvoir faire un vecteur ou une pile des objets, et être libre pour mettre n'importe quel
type d'objet dans lui. Naturellement vous devez connaître quel type d'objet il est quand vous
lui accédez, mais comme la causerie, Java vous laisse demander l'objet « quel type c'est. »
Cette fonction apparemment simple ajoute un bon nombre de puissance à la langue.
Autonomie
Pour qu'un logiciel soit autonome, ce doit être un processus ou un fil séparé. Les applications
de Java sont des processus séparés et car telles peuvent être longues et autonomes. Une
application de Java peut communiquer avec d'autres programmes using des douilles. Dans une
application, un agent peut être un fil séparé de commande. Java soutient des applications
filetées et fournit l'appui pour l'autonomie using les deux techniques.
Dans l'introduction, nous avons décrit les agents intelligents en tant que des programmes ou
processus autonomes. En soi, ils sont toujours attente, prêtes à répondre à une demande
d'utilisateur ou à un changement de l'environnement. Une question qui vient à l'esprit est
« comment fait l'agent savent quand quelque chose change ? » Dans notre modèle, comme
avec beaucoup d'autres, l'agent est informé en lui envoyant un événement. D'une perspective
de conception orientée objectivement, un événement n'est rien davantage qu'un appel ou un
message de méthode, avec l'information passée le long à l'appel de méthode qui définit ce qui
s'est produit ou les quels action nous voulons que l'agent effectue, comme eus besoin pour
traiter l'événement.
Java soutient également une autre interface de plus haut niveau d'événement appelée le cadre
observable/observateur. Dans cette approche, les objets ou les observateurs intéressés
s'enregistrent avec l'objet observable. Toutes les fois qu'une méthode est invitée la chose
observable ou l'objet de modèle qui cause un changement crucial d'état ou quelque chose
équivalente à un événement sémantique à niveau élevé, puis on annonce tous les objets
enregistrés d'observateur.
Intelligence
L'intelligence dans les agents intelligents peut s'étendre de la logique procédurale ou orientée
objectivement hardcoded aux possibilités sophistiquées de raisonnement et d'étude. Tandis
que le Prolog et blèsent sont les deux langues habituellement liées à l'intelligence artificielle
planifiant, ces dernières années, une grande partie du travail commercial d'AI a été codé dans
C et C++. Comme un langage de programmation d'usage universel et orientée objectivement,
Java fournit toute les fonction basse requise pour soutenir ces comportements.
Mobilité
Il y a plusieurs différents aspects à la mobilité dans le cadre des agents intelligents et des
applications intelligentes. Les bytecodes de Java et les dossiers portatifs de FIOLE permettent
à des groupes de classes de Java compilées d'être envoyés au-dessus d'un réseau et d'être puis
exécutés sur la machine cible. Les Java applets Fournissent un mécanisme pour courir le code
de Java à distance par l'intermédiaire d'un web browser. D'autres environnements, tels que les
ferrets d'IBM, permettent à des processus de Java d'être commencés, suspendus, et déplacés.
Une des conditions principales pour des programmes mobiles est la capacité de sauver l'état
du processus courant, l'embarque au loin, et reprend alors où la gauche de processus au loin,
seulement maintenant elle fonctionne sur un système différent. Les chercheurs de
l'informatique ont exploré cette matière dans le grand détail par rapport à l'équilibrage de la
charge sur les systèmes informatiques répartis tels que des réseaux des postes de travail. Avoir
les machines homogènes était une partie cruciale de faire ce travail. De nouveau, la machine
virtuelle de Java vient à la délivrance. En fournissant un environnement de calcul standard
pour qu'un processus de Java coure dedans, le JVM fournit une machine virtuelle homogène
qui permet à des agents de Java de se déplacer entre les systèmes de matériel hétérogènes
(d'un PC à un poste de travail de Sun, à un système d'AS/400) sans perdre un battement.
Résumé
• Java est une langue portative et architecture-neutre, parce qu'il est compilé dans les
bytecodes qui sont alors interprétés et courent par la machine virtuelle de Java. N'importe
quel système qui soutient la machine virtuelle de Java peut lancer n'importe quel
programme pur de Java.
• Des compilateurs juste à temps sont employés pour convertir des bytecodes en de langage
machine pour améliorer l'exécution. Les compilateurs statiques sont également disponibles
pour transformer le code source de Java directement en executables platform-specific.
• Java ne fournit pas des indicateurs ou des opérateurs pour la manipulation des indicateurs.
Toute l'attribution de mémoire est commandée par le programmeur employant le nouvel
opérateur. Le stockage d'objet (mémoire) est récupéré par une fonction automatique de
collection d'ordures.
• Les Java applets Sont les petits programmes de Java qui peuvent être téléchargés d'un
serveur à un client et à une course par un web browser en tant qu'élément d'un HTML page.
Pour des raisons de sécurité, les applet sont restreints d'accéder aux ressources locales.
Cependant, Java soutient les applications autonomes qui sont équivalentes aux programmes
standard de C ou de C++, et qui ont accès sans restriction aux ressources du système.
• Java est un langage de programmation orientée objectivement avec la syntaxe de C++. Une
classe de Java contient les membres et les méthodes de données qui définissent l'état et le
comportement des exemples ou des objets de cette classe. En plus des objets, Java soutient
les types de données élémentaires pour l'exécution.
• L'interface indigène de méthode de Java permet des programmes courant le Java machine
virtuelle pour appeler des interfaces de programme d'application écrites dans C et C++. Elle
permet également des programmes écrits en d'autres langues pour commencer vers le haut
la VM de Java et pour lancer des programmes de Java.
• Java emploie le jeu de caractères de 16 bits d'Unicode pour le texte de codage. Le format
d'Unicode soutient la plupart des langues principales dans le monde, y compris le Japonais, le
Coréen, et le Chinois.
LY_SII __ 35 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
• La langue de Java est prolongée par un ensemble de paquets, qui contiennent les classes
de soutien pour une large variété de fonctions, y compris les communications de réseau
(java.net), la sécurité (java.security), les interfaces utilisateurs graphiques (java.awt), les
appels à distance de méthode (java.rmi), et l'accès aux bases de données (java.sql).
• JavaBeans est l'architecture de composant de logiciel de Java. Des haricots peuvent être
employés dans un environnement visuel de constructeur pour construire des applications
hors des composants de logiciel existants, y compris des composants d'ActiveX.
• Java fournit toute les fonctionnalité exigée pour concevoir et mettre en application les
agents intelligents. Ses possibilités de langage de type objet d'usage universel et permettent
à la connaissance d'être représentés et raisonnement et à algorithmes d'étude à mettre en
application facilement. Les bytecodes portatifs de Java permettent à des agents d'être
empaquetés comme applet ou en tant que programmes mobiles de Java.
Exercices
1. Si vous n'avez pas déjà fait ainsi, obtenir commencé à apprendre Java. Le site Web chez
http://java.sun.com a un excellent cours d'instruction en ligne sur Java comprenant des
descriptions des perfectionnements de JDK 1.1.
3. Écrire bonjour un applet du monde. Le courir using la visionneuse d'applet ou votre web
browser préféré. Passer votre nom dans l'applet ainsi il montre « bonjour le name>> de
<<your ! » Pouvez-vous passer dans un type de valeur de paramètre ?
LY_SII __ 36 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Chapitre 2
Problem résolvant Using la recherche
En ce chapitre nous explorons la première poussée de commandant de la
recherche en matière d'intelligence artificielle, résolution des problèmes using la
recherche. Nous discutons comment des problèmes peuvent être représentés
comme états et être puis résolus suivre des techniques simples de recherche de
force brutale ou des méthodes tout à fait sophistiquées de recherche heuristique.
On développe un Java applet Qui met en application quatre algorithmes de
recherche de base.
Définition du problème
Le centre de beaucoup de recherche d'AI a été sur résoudre des problèmes. Tandis que
quelques critiques ont argué du fait que l'AI s'est concentrée sur de manière irréaliste des
problèmes simples ou de jouet dans le passé, ce n'est certainement pas le cas aujourd'hui.
Rétrospectivement, il n'est pas clair que les critiques « de problème de jouet » aient été
justifiées du tout. Une grande partie du point de la recherche d'AI était de comprendre
« comment » résoudre le problème, pour obtenir pas simplement une solution. Les problème-
puzzles tellement apparemment simples, jeux, empilant bloquer-étaient le centre des
programmes d'AI. Et un des premiers domaines, des méthodes de résolution des problèmes
générales, a accentué une barrière importante au logiciel d'intelligence artificielle. Comment
représentez-vous un problème de sorte que l'ordinateur puisse le résoudre ? Même avant cela,
comment définissez-vous le problème avec assez de précision de sorte que vous puissiez
figurer dehors comment la représenter ?
Tandis que « savoir dans quelles affaires vous êtes » est une des maximes élémentaires
d'affaires, parce que d'intelligence artificielle qu'elle « sait quel problème vous essayez de
résoudre. » Pour certains, la solution du problème est avec succès le seul but. Pourquoi utiliser
un ordinateur à moins qu'il puisse l'aide vous résoudre des problèmes commerciaux (et gagner
l'argent) ? Pour d'autres, le défi est de reproduire des techniques de résolution des problèmes
humaines ou, au moins, de gagner un meilleur arrangement de la façon dont les gens résolvent
des problèmes complexes. Aujourd'hui, très peu de personnes réclameraient que les méthodes
rechercher-basées démontrent comment notre cerveau résout des problèmes, mais ces
méthodes ont prouvé extrêmement utile et ont un endroit dans n'importe quel examen des
techniques IA Pratiques.
La première étape dans n'importe quel exercice de résolution des problèmes est définissent à
clairement et succinctement ce que c'est nous essayent de faire. Voulons-nous trouver le
meilleur itinéraire pour un voyage ou juste celui qui nous y arriveront ? Pouvons-nous
attendre plusieurs heures ou jours une réponse, ou avons-nous besoin de la meilleure réponse
que nous pouvons calculer en dix secondes ? Quelqu'un une fois que dit que dans l'AI la
plupart de part importante de résolution des problèmes est « représentation, représentation, la
représentation. » En ce chapitre, nous sommes intéressés par la façon représenter notre
problème de sorte que nous puissions le résoudre using des techniques de recherche, et qui
recherchent des techniques pour employer. Dans la prochaine section, nous explorons une des
représentations primaires de problème, l'approche du l'état-espace.
LY_SII __ 37 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
L'espace d'état
Supposer que le problème que nous voulons résoudre des affaires avec jouer et gagner un jeu.
Ce jeu a pu être simple tel que le tic-tac-orteil ou plus complexe tel que des contrôleurs, des
échecs, ou le jacquet. En tous cas, la clef à traiter ce problème avec un ordinateur est de
développer une cartographie du monde du jeu-espace des morceaux et le modèle géométrique
sur un conseil, à une structure de données qui capture l'essence du jeu-état courant. Pour le tic-
tac-orteil, nous pourrions employer une rangée avec neuf éléments, ou nous pourrions définir
des 3 par la matrice 3 avec 1s et 0s pour dénoter le Xs et l'OS de chaque joueur.
Nous commençons par un premier état, qui dans le cas de tic-tac-orteil pourrait être des 3 par
la matrice 3 remplie d'espaces (ou de marqueurs vides). Pour n'importe quel état de notre
panneau de jeu, nous prenons un ensemble d'opérateurs qui peuvent être employés pour
modifier l'état actuel, créant de ce fait un nouvel état. Dans notre cas, ce serait un joueur
marquant un espace vide avec un X ou un O. La combinaison de l'état initial et l'ensemble
d'opérateurs composent l'espace d'état du problème. L'ordre des états produits par la demande
valide des opérateurs à partir de l'état initial s'appelle le chemin dans l'espace d'état.
Maintenant que nous avons les moyens d'aller de notre état initial aux états valides
additionnels de jeu, nous devons pouvoir détecter quand nous avons atteint notre état de but.
Dans le tic-tac-orteil un état de but est quand n'importe quelle rangée, colonne, ou diagonale
se compose de tout le Xs ou OS. Dans cet exemple simple, nous pouvons vérifier le panneau
de tic-tac-orteil pour voir si l'un ou l'autre joueur a gagné en déterminant explicitement notre
état de but. Dans des problèmes plus compliqués, la définition de l'essai de but peut être un
problème substantiel en soi.
Les algorithmes de recherche efficaces doivent faire deux choses : le mouvement de cause ou
le traversal de l'espace d'état, et font ainsi d'une façon commandée ou systématique. La
recherche aléatoire peut fonctionner dans quelques problèmes, mais généralement nous
devons rechercher d'une manière organisée et méthodique. Si nous avons une stratégie de
recherche systématique qui n'emploie pas des informations sur le problème pour aider direct
la recherche, ce s'appelle la recherche de la force brutale, non informée, ou sans visibilité. La
seule différence entre les différentes techniques de recherche de force brutale est l'ordre dans
lequel des noeuds sont augmentés. Mais même les légers changements de l'ordre peuvent
avoir un impact significatif sur le comportement de l'algorithme. Des algorithmes de
recherche qui emploient des informations sur le problème, tel que le coût ou la distance à
l'état de but, s'appellent recherche heuristique, au courant, ou dirigée. L'avantage primaire des
algorithmes de recherche heuristique est que nous pouvons faire de meilleurs choix au sujet
LY_SII __ 38 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
dont noeud à augmenter après. Ceci améliore sensiblement l'efficacité des algorithmes de
recherche.
Stratégies de recherche
Dans cette section nous examinons deux techniques de base de recherche employées pour
résoudre des problèmes dans l'AI, la recherche en largeur et la profondeur-première
recherche. Plus tard nous explorerons des perfectionnements à ces algorithmes, mais d'abord
nous devons nous assurer que nous comprenons comment ces approches de base fonctionnent.
Nous travaillerons par plusieurs exemples, using la carte représentée sur le schéma 2.1.
D'abord, nous devons définir le problème que nous essayons de résoudre. Dans ce cas-ci, il est
tout à fait simple. Donné un point de départ à des villes sur la carte, pouvons-nous trouver une
autre ville sur la carte tant que il y a une ville de chemin dès le début à la ville d'extrémité ou
de but ? Actuellement, nous n'essayons pas de trouver le Shortest-Path ou n'importe quoi de
pareil. Nous voulons simplement trouver si la ville de but est sur la carte.
L'ok, maintenant que nous avons défini le problème, la prochaine étape est de décider
comment représenter le problème comme état-espace. Une carte comme celle sur le schéma
2.1 peut être naturellement représentée par une structure de données de graphique, où les
noms de villes sont les noeuds, et les chaussées principales entre les villes sont les liens ou les
bords du graphique. Ainsi, d'une perspective de programmation, notre problème est de
traverser une structure de données de graphique d'une manière systématique jusqu'à nous
trouvent la ville de but ou épuisent toutes les possibilités. Avoir si tout va bien l'état-espace
entier montré sur une carte facilitera comprenant les opérations des algorithmes de recherche.
Dans des problèmes plus complexes, tout que nous avons est l'état simple de début et un
ensemble d'opérateurs qui sont habitués pour produire de plus en plus de nouveaux états. Les
algorithmes de recherche fonctionnent la même manière, mais conceptuellement, nous
sommes s'élevants ou augmentant le graphique, au lieu de l'avoir a spécifié au début.
Recherche en largeur
L'algorithme suit :
L'algorithme en largeur étend dans un noeud uniforme de façon dès le début. Dès le début, il
regarde chaque bord du noeud un loin. Alors il sort de ces noeuds à tous les noeuds deux
bords à partir du début. Ceci continue jusqu'à ce qu'ou le noeud de but soit trouvé ou l'arbre
entier est recherché. La recherche en largeur est complète ; elle trouvera une solution si on
existe. Mais elle n'est ni optimale dans le cas général (elle ne trouvera pas la meilleure
solution, juste le premier qui assortit l'état de but), ni elle a le bon temps ou complexité de
l'espace (elle se développe exponentiellement dans la consommation de temps et de
mémoire).
Marchons par un exemple pour voir comment la recherche en largeur pourrait trouver une
ville sur notre carte. Notre recherche commence à Rochester, et nous voulons savoir si nous
pouvons obtenir à Wausau de là. Le noeud de Rochester est placé sur la file d'attente dans
l'étape 1. Après nous écrivons notre boucle de recherche à l'étape 2. Nous enlevons Rochester,
le premier noeud de la file d'attente. Rochester ne contient pas notre état de but (Wausau)
ainsi nous l'augmentons en prenant chaque noeud d'enfant à Rochester, et en les ajoutant au
dos de la file d'attente. Ainsi nous ajoutons [les automnes de Sioux, Minneapolis, LaCrosse,
et le Dubuque] à notre file d'attente de recherche. Maintenant nous sommes en arrière au
dessus de notre boucle. Nous enlevons le premier noeud de la file d'attente (automnes de
Sioux) et l'examinons pour voir si c'est notre état de but. Il n'est pas, ainsi nous l'augmentons,
ajoutant Fargo et Rochester à l'extrémité de notre file d'attente, qui contient maintenant
[Minneapolis, LaCrosse, Dubuque, Fargo, et Rochester]. Nous enlevons Minneapolis, les
échouer d'essai de but, et nous augmentons ce noeud, ajoutant St.Cloud, Wausau, Duluth,
LaCrosse, et Rochester à la file d'attente de recherche, se tenant maintenant [LaCrosse,
Dubuque, Fargo, Rochester, St.Cloud, Wausau, Duluth, LaCrosse, et Rochester]. Nous
examinons le LaCrosse et puis l'augmentons, ajoutant Minneapolis, GreenBay, Madison,
Dubuque, et Rochester à la liste, qui a maintenant devenu [Dubuque, Fargo, Rochester,
St.Cloud, Wausau, Duluth, LaCrosse, Rochester, Minneapolis, GreenBay, Madison,
Dubuque, et Rochester]. Nous enlevons Dubuque et ajoutons Rochester, LaCrosse, et
Rockford à la file d'attente de recherche.
En ce moment, nous avons examiné chaque noeud qui est un niveau dans l'arbre à partir du
noeud de début (Rochester). Notre file d'attente de recherche contient les noeuds suivants :
[Fargo, Rochester, St.Cloud, Wausau, Duluth, LaCrosse, Rochester, Minneapolis,
GreenBay, Madison, Dubuque, Rochester, Rochester, LaCrosse, et Rockford]. Nous
enlevons Fargo, qui est deux niveaux à partir de Rochester, et ajoutons les fourchettes
grandes, le nuage de rue, et les automnes de Sioux. Alors nous examinons et augmentons
Rochester (Rochester vers Minneapolis vers Rochester est deux niveaux à partir de notre
LY_SII __ 40 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
début). Est après le nuage de rue ; encore nous augmentons ce noeud. En conclusion, nous
obtenons à Wausau ; notre essai de but réussit et nous déclarons le succès. Notre ordre de
recherche était Rochester, automnes de Sioux, Minneapolis, LaCrosse, Dubuque, Fargo,
Rochester, nuage de rue, et Wausau.
Noter que cette trace pourrait avoir été considérablement simplifiée en maintenant les noeuds
qui avaient été examinés et augmentés. Ceci aurait réduit notre temps et complexité de
l'espace, et avait toujours été un algorithme complet parce que nous aurions recherché chaque
noeud avant que nous nous soyons arrêtés. Cependant, dans des problèmes plus réalistes où
chaque noeud est augmenté using une liste d'opérateurs et les états sont plus complexes que
juste des cordes, il n'est pas aussi facile de déterminer que deux états sont identiques. Cette
explosion des noeuds et des états n'est pas peu commune pour un problème de recherche en
largeur.
Profondeur-Première recherche
Noter que cet algorithme est identique à la recherche en largeur excepté l'étape 2d. Le
profondeur-premier algorithme recherche dès le début ou noeud de racine toute la manière
vers le bas à un noeud de feuille. S'il ne trouve pas le noeud de but, il fait marche arrière vers
le haut de l'arbre et recherche en bas du prochain chemin non essayé jusqu'à ce qu'il atteigne
la prochaine feuille. Si vous imaginez un grand arbre, le profondeur-premier algorithme peut
passer un grand nombre de temps recherchant les chemins sur le gauche inférieur quand la
réponse est vraiment dans la droite inférieure. Mais puisque la profondeur-première recherche
est une méthode de force brutale, il suivra aveugle ce modèle de recherche jusqu'à ce qu'il
trouve un noeud contenant l'état de but, ou il recherche l'arbre entier. la Profondeur-première
recherche a des conditions de mémoire inférieure que la recherche en largeur, mais elle n'est
ni complète ni optimale.
Comme nous avons fait en haut, marchons par un exemple simple de la façon dont la
profondeur-première recherche fonctionnerait si nous commencions à Rochester et a voulu
voir si nous pourrions obtenir à Wausau. Commençant par Rochester, nous l'examinons et
augmentons, plaçant les automnes de Sioux, puis Minneapolis, puis le LaCrosse, puis le
Dubuque à l'avant de la file d'attente de recherche [Dubuque, LaCrosse, Minneapolis,
automnes de Sioux]. Nous enlevons Dubuque et l'examinons ; il échoue, ainsi nous
LY_SII __ 41 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
l'augmentons ajoutant Rochester à l'avant, puis LaCrosse, puis Rockford. Notre file
d'attente de recherche ressemble maintenant à [Rockford, LaCrosse, Rochester, LaCrosse,
Minneapolis, automnes de Sioux]. Nous enlevons Rockford, et ajoutons Dubuque,
Madison, et Chicago à l'avant de la file d'attente dans cet ordre, rapportant [Chicago,
Madison, Dubuque, LaCrosse, Rochester, LaCrosse, Minneapolis, automnes de Sioux].
Nous examinons Chicago, et endroit Rockford, et Milwaukee sur la file d'attente. Nous
prenons Milwaukee de l'avant et ajoutons Chicago, Madison, et Green Bay à la file
d'attente de recherche. Elle est maintenant [Green Bay, Madison, Chicago, Rockford,
Chicago, Madison, Dubuque, LaCrosse, Rochester, LaCrosse, Minneapolis, automnes de
Sioux]. Nous enlevons le Green Bay et ajoutons Milwaukee, LaCrosse, et Wausau à la file
d'attente dans cet ordre. En conclusion, Wausau est à l'avant de la file d'attente et notre essai
de but réussit et nos extrémités de recherche. Notre ordre de recherche était Rochester,
Dubuque, Rockford, Chicago, Milwaukee, Green Bay, et Wausau.
Dans cet exemple, nous encore n'avons pas empêché des noeuds examinés d'être ajouté à la
file d'attente de recherche. En conséquence, nous avons eu des noeuds doubles sur la file
d'attente. Dans le profondeur-premier cas, ceci pourrait avoir été désastreux. Nous pourrions
avoir facilement eu un cycle ou faire une boucle où nous avons examiné une ville, puis un
deuxième, puis le premier encore, ad infinitum. Dans la prochaine section, nous montrons
notre exécution de Java de ces algorithmes de recherche, commençant par une classe pour le
noeud et une pour le graphique de recherche. Nous incluons des essais pour éviter cette
duplication des essais et les noeuds sur la recherche s'alignent.
La classe de SearchNode
Ces problèmes sont définis using une structure hiérarchique d'arbre ou de graphique, consistée
en un ensemble de noeuds et de liens. Nos algorithmes de recherche travaillent à une structure
de noeud que nous avons définie comme classe de Java SearchNode. Les constructeurs de
SearchNode et les membres de données sont montrés ci-dessous :
Le premier membre de données dans notre classe de SearchNode est le nom symbolique ou
l'étiquette du noeud. Est après l'état, qui peut être n'importe quel objet. L'opération est la
LY_SII __ 42 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
définition de l'opération qui a créé l'état de l'objet. Ceci serait employé dans les problèmes tels
que des jeux où l'état d'un noeud de parent serait augmenté dans des noeuds et des états
d'enfant multiples basés sur l'application de l'ensemble d'opérateurs.
Le membre de liens est un vecteur contenant des références à tous autres objets de
SearchNode auxquels ce noeud est lié. Des objets de SearchNode peuvent être reliés pour
former n'importe quel graphique comprenant les structures arborescentes.
Le membre de profondeur est un nombre entier qui définit la distance dès le début ou le noeud
de racine dans n'importe quelle recherche. Les deux drapeaux booléens, augmentés et
examinés, sont employés par les algorithmes de recherche pour éviter d'entrer dans les boucles
infinies. Le premier, augmenté, est placé toutes les fois que le noeud est augmenté pendant
une recherche. La seconde, examinée, est employée toutes les fois que l'état du noeud est
examiné pendant une recherche. Selon l'algorithme de recherche ce drapeau mai ou mai ne
pas être employé. Le membre de coût peut être employé pour représenter le coût accumulé
courant ou n'importe quelle autre mesure de coût liée au problème de recherche. Le membre
statique textArea1 est habitué pour montrer l'information de trace dans notre applet d'exemple.
Une fois que nous avons créé un exemple d'un SearchNode, nous devons spécifier les liens à
d'autres noeuds. L'addLink () et des méthodes d'addLinks () sont fournis à cette fin. Des
méthodes sont données pour ajouter un, deux, trois, ou quatre liens à d'autres objets de
SearchNode aussi bien qu'un vecteur des objets de SearchNode une fois nécessaires pour les
graphiques très grands en connectivité élevée.
Nous fournissons un ensemble de méthodes pour l'essai si le noeud est un noeud de feuille
dans une structure arborescente (c.-à-d., elle n'a aucun enfant) et des méthodes pour placer la
profondeur, l'opération, augmentée, et les membres d'essais.
La méthode de remise () est employée pour remettre à zéro la profondeur de noeud et les
drapeaux booléens avant de commencer une recherche.
La méthode setDisplay() est employée dans notre applet d'exemple pour enregistrer un
composant de TextArea pour montrer l'information de trace pendant une recherche.
La méthode de trace () écrit une corde dentelée indiquant la profondeur du noeud dans l'arbre
de recherche avec son étiquette et état. Comme écrit, elle suppose que l'état est une corde.
La méthode la plus compliquée dans notre classe de SearchNode est la méthode d'expansion
(), qui est employée par les divers algorithmes de recherche pour accumuler un arbre de
recherche du graphique de recherche initial. Les paramètres sont une file d'attente (un
exemple de vecteur) et un paramètre spécifiant où les noeuds d'enfant devraient être placés
sur la file d'attente. Les options sont AVANT, ARRIÈRES, ou INSERTION, basée sur le coût
courant dans le SearchNode.
D'abord nous marquons le noeud comme augmenté. Alors nous faisons une boucle au-dessus
de tous les noeuds auxquels le noeud a des liens. Pour chaque noeud, s'il n'a pas été examiné
LY_SII __ 44 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
(réellement, ce des moyens placés sur la file d'attente, parce que les états de noeud sont
examinés seulement quand ils sont enlevés de l'avant de la file d'attente) nous la marquons
comme examiné, plaçons sa profondeur dans l'arbre de recherche, et puis la plaçons sur la file
d'attente en position spécifique. Pour l'AVANT, nous ajoutons à la position 0. Pour le DOS
nous simplement addElement (), qui le place à la fin du vecteur.
Pour la caisse d'INSERTION, nous prenons une boucle où nous comparons le coût du noeud
que nous essayons de nous insérer, nextNode, au coût des noeuds sur la file d'attente. Si le
nextCost est inférieur, nous le plaçons sur la file d'attente. Il y a deux cas où le nextNode ne
sera pas inséré dans cette boucle : quand la file d'attente est vide, et quand le nextCost est plus
grand que le coût de tous les noeuds déjà sur la file d'attente. Nous employons un drapeau
booléen, inséré, pour traiter ces cas.
Maintenant que nous avons défini notre classe de SearchNode, nous pouvons parler de notre
classe de SearchGraph, qui contient l'ensemble d'objets de SearchNode qui définissent nos
états de problème. SearchGraph est une classe relativement simple. Il prolonge le
java.util.La classe de table de brouillage en ajoutant un nom et un ensemble de méthodes
pour des opérations de manipulation sur une collection de SearchNode objecte. Le
constructeur prend un paramètre simple de corde pour le nom de SearchGraph. Le
comportement de table de brouillage de défaut est prolongé par deux méthodes. La méthode
de remise () emploie l'énumération des éléments dans la table de brouillage pour réitérer au-
dessus des objets de SearchNode et pour remettre à zéro chacun alternativement. () La
LY_SII __ 45 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
méthode mise prend un objet de SearchNode comme argument simple, et puis appelle () la
méthode mise par table de brouillage using l'étiquette comme clef et l'objet de SearchNode
comme valeur.
SearchGraph(String Name) {
name = Name ;
}
Applet de recherche
Dans cette section, nous développons un Java applet Pour illustrer le comportement de quatre
algorithmes de recherche. L'interface utilisateurs de notre applet est composée d'un dialogue
simple représenté sur le schéma 2.2. Un utilisateur peut choisir parmi une de quatre
techniques de recherche : profondeur-premier, en largeur, réitérer-approfondissement, et
meilleur-premier. Nous avons déjà présenté les algorithmes en largeur et profondeur-premiers
de manière assez détaillée. Nous discuterons chacun des quatre algorithmes et leurs
réalisations dans les sections suivantes. L'utilisateur peut choisir l'état de début et de but dans
notre essai SearchGraph avec le type. Le pressurage du bouton marche appellera
l'algorithme de recherche correspondant avec les états spécifiques de noeud et de but de début
passés comme arguments. Pendant que les algorithmes de recherche progressent, l'information
de trace est montrée dans le TextArea au dessus du dialogue. Appuyer sur le bouton clair
dégagera ce secteur entre les courses, si désiré.
Un testGraph statique simple de méthode () est défini dans notre SearchApplet qui crée un
échantillon SearchGraph pour nos exemples des différents algorithmes de recherche. Ce
graphique définit l'ensemble de villes du Mid-West des États-Unis suivant les indications du
schéma 2.1. D'abord nous instancions l'objet de SearchGraph et puis un SearchNode pour
chaque ville. Après que chaque objet de SearchNode soit créé, il est ajouté au SearchGraph
en employant () la méthode mise héritée de la table de brouillage. Noter que le nom de
LY_SII __ 46 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
noeud et l'état (aussi le nom de la ville) sont identiques. C'est pour l'illustration seulement. Il
n'y a aucune raison pour laquelle l'étiquette de noeud et l'état doivent être identique. En fait, le
deuxième paramètre sur le constructeur de SearchNode peut être n'importe quel objet de
Java. Ainsi nous pourrions avoir une rangée ou une matrice pour le tic-tac-orteil, ou une autre
représentation arbitrairement complexe du l'état-espace, selon le problème que nous essayons
de résoudre.
Après que les objets de SearchNode soient créés, nous définissons alors la connectivité entre
les noeuds suivre la méthode d'addLinks (). Après, nous avons placé le coût de chaque noeud
comme distance de chaque ville vers Rochester, Minnesota. Nous employons ceci dans le
meilleur-premier exemple de recherche discuté plus tard dans cette section. Cette valeur de
coût est placée à une valeur statique pour cet exemple. Dans la plupart des problèmes de
recherche, le coût serait calculé comme recherche progresse. C'est une autre simplification
employée pour rendre les explications complémentaires plus claires.
// build a test graph and then call the specified search routine
// this graph is a set of cites in the mid-west United States
public static SearchGraph testGraph() {
return graph ;
}
Quand le bouton marche est pressé, un awt. L'événement est produit et le code suivant est
appelé. D'abord nous recherchons les cordes de début et de but des commandes bien choisies.
Après nous dégageons tous les objets de SearchNode dans le graphique en appelant la remise
(). Alors nous vérifions l'état des boutons par radio using le getState () et appelons
l'algorithme de recherche choisi. Seulement un radiobutton peut être choisi à tout moment.
if (answer == null) {
textArea1.appendText(“Could not find answer!\n”);
} else {
textArea1.appendText(“Answer found in node ” +
answer.label);
}
}
Quand le bouton clair est appuyé sur, nous dégageons dehors le TextArea.
Dans une boucle de moment (), nous vérifions d'abord pour voir s'il y a plus de noeuds à
augmenter. Si oui, nous enlevons le premier noeud, appelons la trace () pour imprimer un
message, alors examinons le noeud pour voir s'il assortit notre état de but. Bien que dans notre
applet d'exemple nous employions des cordes pour représenter notre état de but, ce code
devrait fonctionner pour n'importe quel objet d'état l'a fourni applique la méthode d'égales ().
Si l'essai de but réussit, nous retournons avec le noeud qui a assorti l'état de but. Si l'essai de
but échoue et nous n'avons pas déjà augmenté ce noeud, nous l'augmentons en plaçant tous les
noeuds qu'il a des liens à sur le dos de la file d'attente. Quand la file d'attente est vide nous
sortons la boucle de moment ().
La recherche en largeur exécute une recherche complète de l'espace d'état. S'il y a les
solutions multiples, il trouvera une solution avec le nombre le plus court d'étapes parce que
chaque noeud de la longueur n est examiné avant que la prochaine couche de noeuds soit
explorée. Sur le schéma 2.3 nous montrons le rendement d'une course de recherche en largeur
contre notre testGraph avec Chicago comme noeud de début et Rochester comme destination.
Noter que l'ordre exact de recherche est affecté par la façon dont nous définissons les liens
dans notre testGraph.
Dans une boucle de moment (), nous vérifions d'abord pour voir s'il y a plus de noeuds à
augmenter. Si oui, nous enlevons le premier noeud, appelons la trace () pour imprimer un
message, alors examinons le noeud pour voir s'il assortit notre état de but. Bien que dans notre
applet d'exemple nous employions des cordes pour représenter notre état de but, ce code
devrait fonctionner pour n'importe quel objet d'état l'a fourni applique la méthode d'égales ().
Si l'essai de but réussit, nous retournons avec le noeud qui a assorti l'état de but. Si l'essai de
but échoue et nous n'avons pas déjà augmenté ce noeud, nous l'augmentons en plaçant tous les
noeuds qu'il a des liens à sur l'avant de la file d'attente. Quand la file d'attente est vide nous
sortons la boucle de moment ().
while (queue.size()> 0) {
SearchNode testNode = (SearchNode)queue.firstElement() ;
queue.removeElementAt(0) ;
testNode.trace() ; // display trace information
if (testNode.state.equals(goalState)) return testNode;
if (!testNode.expanded) {
testNode.expand(queue,SearchNode.FRONT);
}
}
return null ;
}
Cet algorithme, comme la recherche en largeur standard, est une recherche complète et
trouvera une solution optimale, mais il a des conditions de mémoire beaucoup inférieure,
comme le profondeur-premier algorithme. Bien que nous retracions la terre quand nous
augmentons notre profondeur de recherche, cette approche est toujours plus efficace que
profondeur-première la recherche illimitée en largeur ou pure pure des grands espaces de
recherche (Russell et Norvig 1995).
while (queue.size()> 0) {
SearchNode testNode = (SearchNode)queue.firstElement() ;
queue.removeElementAt(0) ;
testNode.trace() ;
if (testNode.state.equals(goalState)) return testNode ;
Sur le schéma 2.5 nous montrons une trace d'une recherche de Chicago à Rochester using
l'algorithme de réitérer-approfondissement. Notification comment l'algorithme récupère la
terre pendant qu'il va à chaque niveau.
Recherche heuristique
Des méthodes de recherche heuristique sont caractérisées par ce sens que nous avons un
temps et un espace limités dans lesquels pour trouver une réponse aux problèmes complexes
et ainsi nous sommes disposés à accepter une bonne solution. En soi, nous appliquons
l'heuristique ou les principes de base pendant que nous recherchons l'arbre pour essayer de
déterminer la probabilité que suivre un chemin ou des autres est pour mener à une solution.
Noter ceci est dans le contraste radical aux méthodes de force brutale indépendamment des
lesquelles souffler le long joyeux si une solution est n'importe où en vue.
produire et l'essai peut être un algorithme efficace, mais pour de grands problèmes, la
stratégie de recherche non dirigée mène aux temps d'exécution prolongés et est impraticable.
La faiblesse principale de se produisent et l'essai est que nous n'obtenons aucune rétroaction
sur laquelle direction à rechercher. Nous pouvons considérablement améliorer cet algorithme
en fournissant la rétroaction par l'utilisation des fonctions heuristiques.
Pour on a proposé éviter d'obtenir a emprisonné dans les états suboptimaux, variations sur la
stratégie s'élevante de colline. On est d'injecter le bruit dans la fonction d'évaluation, avec la
haute initiale de niveau de bruit et diminuer lentement avec le temps. Cette technique, appelée
le recuit simulé, permet à l'algorithme de recherche d'aller dans les directions qui ne sont pas
« les meilleures » mais de permettre une exploration plus complète de l'espace de recherche.
Le recuit simulé est analogue au recuit des métaux, par lequel elles soient heated et alors
graduellement refroidies. Ainsi un paramètre de la température est employé dans le recuit
simulé, où une température laisse plus de recherche, mais pendant que la température se
refroidit, l'algorithme de recherche retourne au comportement s'élevant de colline plus
standard (Kirkpatrick, Gelatt, et Vecchi 1983).
Dans la prochaine section nous décrivons la meilleur-première recherche, qui est des
spécifications plus formelles d'un avide, type s'élevant algorithme de colline de recherche.
Dans une boucle de moment (), nous vérifions d'abord pour voir s'il y a plus de noeuds à
augmenter. Si oui, nous enlevons le premier noeud, appelons la trace () pour imprimer un
message, alors examinons le noeud pour voir s'il assortit notre état de but. Bien que dans notre
applet d'exemple nous employions des cordes pour représenter notre état de but, ce code
devrait fonctionner pour n'importe quel objet d'état l'a fourni applique la méthode d'égales ().
Si l'essai de but réussit, nous retournons avec le noeud qui a assorti l'état de but. Si l'essai de
but échoue et nous n'avons pas déjà augmenté ce noeud, nous l'augmentons en plaçant tous les
noeuds qu'il a des liens à sur l'avant de la file d'attente. Quand la file d'attente est vide nous
sortons la boucle de moment ().
while (queue.size()> 0) {
SearchNode testNode = (SearchNode)queue.firstElement() ;
queue.removeElementAt(0) ;
testNode.trace() ;
if (testNode.state.equals(goalState)) return testNode ;
La recherche avide de recherche avide est une meilleur-première stratégie où nous essayons
de réduire au minimum le coût estimatif pour atteindre le but (certainement une approche
intuitive !). Puisque nous sommes avides, nous augmentons toujours le noeud on estime que
qui est le plus proche de l'état de but. Malheureusement, le coût exact d'atteindre l'état de but
habituellement ne peut pas être calculé, mais nous pouvons l'estimer en employant une
estimation des coûts ou une fonction heuristique h (). Quand nous examinons le noeud n, alors
h (n) nous donne le coût estimatif du chemin le meilleur marché de l'état du n à l'état de but.
Naturellement, le meilleur une évaluation h () donne, le meilleur et plus rapide nous trouvera
une solution à notre problème. La recherche avide a le comportement semblable à la
profondeur-première recherche. Ses avantages sont fournis par l'intermédiaire de l'utilisation
d'une fonction heuristique de qualité de diriger la recherche.
La recherche une d'A* des algorithmes de recherche les plus célèbres utilisés dans l'AI est
l'algorithme de recherche d'A*, qui combine l'algorithme de recherche avide pour l'efficacité
avec la recherche d'uniforme-coût de l'optimalité et de la perfection. Dans A* la fonction
d'évaluation est calculée en ajoutant les deux mesures heuristiques ; le h (n) estimation des
LY_SII __ 55 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
coûts de traversée de n à l'état de but, et g (n) qui est le chemin connu coûter dès le début le
noeud à n dans une fonction appelée le f (n).
Encore, il n'y a rien vraiment nouveau ici d'un point de vue d'algorithme de recherche ; tout
que nous faisons emploie la meilleure information (heuristique) pour évaluer et commander
les noeuds sur notre recherche aligner. Nous savons combien cela a coûté d'obtenir où nous
sommes (le noeud n) et nous pouvons guesstimate combien cela coûtera d'atteindre le but du
N. De ce fait nous apportons toute les information au sujet du problème que nous pouvons
concerner diriger notre recherche. Cette combinaison des stratégies s'avère fournir à A* la
perfection et l'optimalité.
Le rôle des contraintes est de lier des variables aux valeurs ou de limiter la gamme des valeurs
qu'elles peuvent prendre, de ce fait réduisant le nombre de combinaisons que nous devons les
explorer. D'abord, un premier ensemble de contraintes sont appliqué et propagé par le
problème, sujet aux dépendances qui existent. Par exemple, si nous fixons une limite de 2000
livres pour un camion de livraison particulier, qui peut immédiatement enlever quelques
articles de la considération. En outre, une fois que nous assignons un objet au camion qui pèse
800 livres, nous pouvons impliquer que maintenant la limite pour les articles additionnels est
de 1200 livres. Si une solution n'est pas trouvée en propageant les contraintes, alors la
recherche est exigée. Ceci peut impliquer de faire marche arrière ou défaire un transfert ou
une attache variable.
côté droit de la règle identifie seulement ces parties de l'état que l'opérateur change. Tellement
chaque opérateur a a avant et après la liste d'états et de changements d'état qui sont seulement
un sous-ensemble de l'espace entier de problème. Une version simplifiée de l'analyse means-
ends est décrite ici (riches et chevalier 1991).
Résumé
En ce chapitre nous avons présenté les algorithmes de recherche principaux utilisés dans des
applications d'intelligence artificielle. Les points principaux incluent :
Exercices
Chapitre 3
Représentation du Knowledge
En ce chapitre nous explorons certaines des techniques employées pour
représenter la connaissance de domaine dans des programmes d'intelligence
artificielle. Nous commençons par un examen de plusieurs genres de
connaissance et de différentes demandes que place de personnes et d'ordinateurs
sur des représentations de connaissance. Nous décrivons les représentations de
connaissance procédurales et déclaratives et suivons avec une introduction à la
logique propositionnelle et d'attribut. Après nous discutons des armatures et les
filets sémantiques, deux ont rapporté des techniques d'intelligence artificielle
pour représenter des concepts et leurs rapports. Le format d'échange de la
connaissance est présenté comme standard industriel naissant pour la
représentation de connaissance. En conclusion, nous discutons le procédé
d'acquisition de la connaissance, où la connaissance experte de domaine est
transformée en base de connaissance pour la résolution des problèmes.
Quelle est la connaissance ? La connaissance est-elle la même chose que des faits ? Le
dictionnaire de Webster (Merriam-Webster 1988) définit la connaissance comme « fait ou état
de savoir quelque chose avec la connaissance gagnée par l'expérience ou l'association. » La
connaissance de gain de personnes à travers qu'expérience-ils voient, entendent, touchent, se
sentent, et goûtent le monde autour de elles. Nous pouvons associer quelque chose que nous
voyons avec quelque chose nous entendons, gagnant de ce fait de nouvelles connaissances au
sujet du monde. Une définition alternative pour la connaissance est « le fait ou l'état de se
rendre compte de quelque chose. » Comment mettons-nous au courant un ordinateur de
quelque chose ? Supposer que nous savons que le soleil est chaud, des boules sommes en
rond, et le ciel est bleu. Ces faits sont la connaissance au sujet du monde. Comment stockons-
nous cette connaissance dans notre cerveau ? Comment pourrions-nous stocker cette
connaissance dans un ordinateur ? Ce problème, appelé la représentation de connaissance, est
un du premier, la plupart des issues fondamentales aux lesquelles les chercheurs en
intelligence artificielle ont dû faire face. Et la réponse qu'ils ont trouvée était des symboles.
Tandis que les psychologues et les neurologistes recherchent toujours la réponse à la façon
dont la connaissance de magasin de personnes dans leurs cerveaux (nous savons elle a
quelque chose faire avec les synapses), dans le domaine de l'intelligence artificielle, des
programmeurs emploient des symboles pour représenter et manoeuvrer la connaissance dans
des ordinateurs. Quel est un symbole ? Un symbole est une chaîne de nombre ou de caractères
qui représente un objet ou une idée. Des cordes et des nombres sont employés parce que les
ordinateurs sont très bons pour les traiter. Ceci s'appelle la représentation interne de la
connaissance. Cependant, les gens sont les plus confortables using un de langage naturel
comme l'anglais pour représenter la connaissance. Ainsi, pour des raisons pratiques, nous
avons besoin des tracés des faits à une représentation d'ordinateur interne et également à une
forme que les gens peuvent comprendre.
LY_SII __ 59 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Représentation procédurale
Peut-être la technique la plus commune pour représenter la connaissance dans des ordinateurs
est la connaissance procédurale. Le code procédural code non seulement des faits (des
constantes ou des variables attachées) mais définit également l'ordre des opérations pour
employer et manoeuvrer ces faits. Ainsi, le code de programme est une manière parfaitement
normale de coder la connaissance procédurale. Si des structures ou les objets de données sont
employés pour modeler le problème, le programme est essentiellement une grande
représentation de connaissance. Les programmes écrits en langues scripting telles que Visual
Basic, Javascript, et LotusScript sont des exemples d'une représentation de connaissance
procédurale. La connaissance de la façon traiter des données est codée dans les structures de
gestion et l'ordre des rapports de programme. Cette logique « hardcoded » n'est pas
typiquement considérée une partie d'AI intrinsèquement, mais peu de vrais programmes d'AI
existent qui ne contiennent pas une certaine quantité de code de commande procédural.
cette connaissance fournit des avantages par rapport au code procédural. Puisque la
connaissance est explicitement représentée, elle peut plus facilement être modifiée. En outre,
la séparation de la logique de commande et des algorithmes de motif de la connaissance nous
permet d'écrire des procédures inferencing optimisées et réutilisables.
Représentation apparentée
Une autre manière de représenter l'information est en forme apparentée, comme cela utilisé
dans des systèmes de base de données relationnelle. Les bases de données relationnelles
fournissent un mécanisme puissant et flexible pour stocker la connaissance, qui est pourquoi
elles presque totalement ont assuré les affaires de stocker l'information dans des systèmes
économiques commerciaux. La connaissance est représentée par des tuples ou des disques
d'informations sur un article, avec chaque tuple contenant un ensemble de champs ou
colonnes définissant des attributs de détail et des valeurs de cet article. En stockant une
collecte d'informations dans une table, nous pouvons employer le calcul apparenté pour
manoeuvrer les données, basées sur les relations définies, et questionnons l'information
stockée dans la table. Le langage d'interrogation structuré est la langue la plus populaire pour
manoeuvrer des données apparentées.
Tandis que les tables de base de données relationnelle sont flexibles, elles ne sont pas bonnes
pour représenter des rapports complexes entre les concepts ou les objets dans le monde réel.
C'est où les systèmes de réseau et de base de données hiérarchique, tels que l'IMS d'IBM, sont
forts. Avoir des liens ou des indicateurs entre les groupes relatifs de données permet les
graphiques hiérarchiques et complexes de réseau à construire. Les techniques IA Des filets
sémantiques et des armatures, discutées en plus détail plus tard en ce chapitre, emploient une
approche semblable pour représenter la connaissance.
Représentation hiérarchique
Un autre type de connaissance est la connaissance dont on peut hériter, qui porte sur des
rapports et des attributs partagés entre les genres ou les classes d'objets. La connaissance
hiérarchique mieux est employée pour représenter des rapports de « AIS », où un type général
ou abstrait (par exemple, boule) est lié à des types plus spécifiques (le caoutchouc, golf, base-
ball, football) qui héritent des propriétés de base du type général. La force de la transmission
d'objet tient compte de la représentation compacte de la connaissance et permet à des
algorithmes de raisonnement de traiter à différents niveaux d'abstraction ou de granularité.
Nous pourrions raisonner au sujet des sports et des attributs communs des boules à un niveau,
ou nous pourrions fouiller dans les détails d'un sport particulier et son type respectif de boule.
L'utilisation des catégories ou des types donne la structure au monde en groupant les objets
semblables ensemble. Using des catégories ou des faisceaux simplifie le raisonnement en
limitant le nombre de choses distinctes que nous devons traiter. Une taxonomie ou une
hiérarchie des objets ou des concepts est une manière utile d'organiser des collections de
catégories, parce qu'elle nous permet de réduire la complexité et de penser à des niveaux plus
élevés d'abstraction si possible.
Using des objets modeler le monde et représenter la connaissance devient de plus en plus
populaire. En plus des bases de données réseau relationnelles et, des bases de données d'objet
LY_SII __ 61 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
qui stockent des données d'objet et les méthodes maintenant sont déployées. Sans compter que
tracer naturellement sur le monde réel, des objets peuvent également être employés pour
modeler des idées abstraites et leurs rapports. Les langages de programmation orientée
objectivement tels que la causerie, le C++, et le Java fournissent un cadre normal pour
représenter la connaissance comme objets, et pour raisonner environ et manoeuvrer ces objets.
Les hiérarchies de transmission et de classe sont des concepts fondamentaux sur lesquels des
programmes objets sont établis, et viennent fondamentalement « pour libre » avec les
représentations de connaissance orientées objectivement.
Capturant la connaissance au sujet des objets dans le monde réel et des mesures nonphysical
telles que le temps sont souvent exigés dans la résolution des problèmes d'AI. Savoir quoi
prévoir a basé sur le temps écoulé d'un événement à l'autre est souvent le cachet du
comportement intelligent. Savoir qu'un ami a juste jeté une boule de neige à votre tête serait la
connaissance utile de sorte que vous ayez pu attacher pour l'impact possible. Connaître quel
ami a jeté la boule de neige pourrait vous aider à déterminer la probabilité de l'obtention
frappée du tout. Mais cette connaissance s'appliquerait seulement pendant une courte période
(2-5 secondes après l'événement de lancement). Les concepts de temps comme avant, après,
et pendant sont cruciaux au raisonnement et à la planification common-sense. Quand nous
essayons de résoudre un problème, nous feignons souvent que le « temps se tient toujours »
tandis que nous faisons notre calcul. Cependant, dans beaucoup de problèmes nous devons
explicitement traiter des changements, dus au dépassement du temps, ou au mouvement des
objets du monde. Des formulaires spéciaux de la logique, appelés la logique temporelle, ont
été développés pour traiter la représentation et des motifs au sujet du temps.
Bien qu'il y ait autant de différentes manières de représenter la connaissance car il y a des
types de connaissance, seulement une poignée de représentations de connaissance sont
employée couramment dans des applications intelligentes artificielles. Dans le reste de ce
chapitre, nous explorons la logique formelle, les armatures, et les filets sémantiques, alors que
dans le prochain chapitre nous explorons les représentations de connaissance basées sur les
règles. Nous commençons notre discussion avec la logique d'attribut.
Logique d'attribut
La logique formelle est une langue avec sa propre syntaxe, qui définit comment faire des
phrases, et sémantique correspondante, qui décrit la signification des phrases. La forme la
plus fondamentale de représentation de logique s'appelle logique booléenne ou
propositionnelle, où chaque proposition ou fait est représentée par un symbole qui évalue à
vrai ou à faux. Des phrases peuvent être construites using les symboles de proposition (P, Q,
R,…) et opérateurs booléens, tels que la conjonction (et), disjonction (ou), implication (P
implique Q), et équivalence (A est équivalent à B). Using cette syntaxe simple, nous
pouvons écrire des implications ou ordonnons, comme (P et Q) implique R ou, plus
programmatically si P et Q puis R. Dans la règle précédente, P et Q s'appelle les lieux ou
LY_SII __ 62 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
La logique booléenne est employée comme base pour concevoir les calculateurs numériques
et est tout adaptée et puissante pour la conception de circuit. Cependant, elle manque
rapidement de vapeur comme langue de représentation de connaissance. Ainsi, la logique
d'attribut, qui permet à des attributs sur des objets de définir des attributs et des relations
entre les objets, est devenue la logique preferred pour la représentation de connaissance dans
des systèmes d'intelligence artificielle. Using des objets, des attributs, et des relations, nous
pouvons représenter presque n'importe quel type de connaissance. En outre, la logique
d'attribut présente le concept des quantifiers, qui nous permettent de nous référer à des
ensembles d'objets. Les deux quantifiers sont existentiels (là existe un certain objet qui a
l'attribut spécifique) et universel (tous les objets de ce type ont cet attribut). Un rapport tel que
le « Minnesota est froid en hiver. » a pu être représenté dans la logique d'attribut de
plusieurs manières. Nous pourrions employer une conjonction des fonctions (dire que jeûnent
trois fois), où les fonctions sont des relations avec un paramètre simple, en tant qu'en place (le
Minnesota) et la température (froide) et la saison (hiver). Ou nous pourrions employer une
relation simple, telle que le froid (Minnesota, hiver). Ou nous pourrions même dire l'hiver
(Minnesota, froids) pour représenter le même rapport.
De ces exemples, vous pouvez voir que la logique d'attribut ne donne aucun conseil quant à
quels attributs nous devrions employer. Ils également n'indiquent pas explicitement comment
le temps ou les événements devrait être représenté. Ce n'est pas de dire que nous ne pouvons
pas représenter ces types de connaissance dans la logique d'attribut. Il peut être fait. La
question principale est de comprendre que même avec la syntaxe et la sémantique définies,
nous avons toujours beaucoup de décisions à faire dans la façon dont la connaissance est
représentée par des attributs.
Mais avoir une bonne représentation de connaissance résout seulement la moitié du problème,
parce que nous devons également manoeuvrer la connaissance pour produire de nouveaux
faits et pour prouver ou réfuter des affirmations sur la connaissance. Malheureusement, la
logique d'attribut ne fournit pas une manière sure-fire de dériver la nouvelle information.
Cependant, elle peut encore être employée pour traiter la connaissance d'une manière utile.
Deux techniques, appelées résolution et l'unification sont employées pour traiter des rapports
d'attribut pour prouver si un rapport particulier est vrai ou pas, basé sur les autres faits connus.
Ensemble ces algorithmes forment la base pour le Prolog (programmant dans la logique). Le
Prolog et blèsent sont les deux langages de programmation traditionnellement utilisés pour
des applications d'intelligence artificielle (Clocksin et Mellish 1981). Tandis que nous
n'entrerons pas dans des détails ici, un arrangement de base des possibilités et des limitations
de la logique d'attribut comme base pour le raisonnement est nécessaire. Notre discussion se
concentrera sur deux mécanismes, résolutions et unifications de base.
Résolution
LY_SII __ 63 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
La résolution est un algorithme pour prouver des faits vrais ou faux en vertu de la
contradiction (Robinson 1965). Si nous voulons nous avérer qu'un théorème X est vrai, nous
devons prouver que la négation de X n'est pas vraie. Par exemple, supposer que nous savons
les deux faits suivants :
La phrase 1 déclare qu'ou Tweety n'a pas des plumes ou bien Tweety est un oiseau. La phrase
2 déclare que Tweety a des plumes. Pour montrer que Tweety est un oiseau, nous ajoutons
d'abord une prétention qui est la négation de cet attribut, donnant la phrase 3 :
Il est clair que les phrases 3 et 4 ne peut pas tous les deux être vrai, ou Tweety est un oiseau
ou il n'est pas. Ainsi, nous avons une contradiction. Nous avons juste montré que notre
première prétention, pas oiseau (Tweety), est fausse, et l'alternative, oiseau (Tweety), doit
être vraie (Winston 1993). Si les clauses à résoudre sont choisies des manières systématiques,
alors la résolution est garantie de trouver une contradiction si on existe, bien que cela puisse
prendre un bon moment de trouver.
Unification
L'unification est une technique pour prendre deux phrases dans la logique d'attribut et trouver
une substitution qui les fait regarder la même chose. C'est une condition pour prouver des
théorèmes using la résolution, comme discuté précédemment. Si deux attributs sont
identiques, alors ils s'assortissent, par définition. Si on ou tous les deux contient des variables,
alors des substitutions appropriées doivent être trouvées using l'unification comme suit :
Etant donné l'ensemble suivant d'attributs, nous laisser explorent comment ils peuvent être
unifiés :
1. haines (X, Y)
LY_SII __ 64 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Nous pourrions unifier la phrase 6 avec la phrase 1 en remplaçant X variable par Z variable et
Y variable avec le broccoli constant. Les phrases 4 et 5 ont pu être unifiées avec George lié à
X, et le broccoli au Y. variable.
Tandis que des attributs peuvent être employés pour représenter et raison avec des règles, tous
les systèmes de règle n'emploient pas la logique d'attribut en tant que leur langue de
représentation de connaissance. Des systèmes basés sur les règles tôt ont été développés using
le Prolog et blèsent, mais la plupart des réalisations commerciales sont maintenant écrites
dans C et C++. En chapitre 4, nous décrirons un système inferencing basé sur les règles
développé using Java.
Vues
Une armature est une collection d'attributs qui définit l'état d'un objet et de son rapport avec
d'autres armatures (objets). Mais une armature est beaucoup plus qu'une structure juste de
disque ou de données contenant des données. Dans l'AI, des armatures s'appellent les
représentations de données de fente-et-remplisseur. Les fentes sont les valeurs de données, et
les remplisseurs sont des procédures jointes avant lesquelles s'appellent, pendant (pour
calculer la valeur de), ou après la valeur de la fente est changé. Des vues sont souvent
incorporées dans une hiérarchie pour représenter l'avoir-partie et les rapports d'AIS.
Si un ordre des actions est appliqué à une armature, alors certains des attributs changent tandis
que les la plupart restent les mêmes. Quand des ordres des opérations sont exigés, comme
dans un problème de recherche, un problème connu sous le nom de problème d'armature
surgit. Le problème est que si nous copions l'armature complète (état de l'objet) pour chaque
étape dans l'ordre, alors nous pouvons rapidement épuiser le de mémorisation par ordinateur,
car nous reproduisons la même connaissance inchangée à plusieurs reprises. Le problème
d'armature traite le problème qui quand une action se produit, il n'est pas toujours évident que
LY_SII __ 65 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
les attributs dans l'armature devraient changer. La solution est de spécifier seulement les
parties de l'état qui doit s'assortir pour qu'une condition soit vrai, et de changer seulement ces
fentes ou attributs qui changent en raison d'un opérateur.
Filets sémantiques
Des filets sémantiques sont employés pour définir la signification d'un concept par ses
rapports avec d'autres concepts. Une structure de données de graphique est employée, avec
des noeuds employés pour tenir des concepts, et des liens avec les étiquettes de langage
naturel employées pour montrer les rapports. Une partie d'une représentation de filet
sémantique du domaine de véhicule est montrée sur le schéma 3.2.
Encore, les rapports standard tels que l'AIS, l'avoir-partie, et l'exemple devraient être au
courant aux lecteurs de l'expérience de conception orientée objectivement. Une grande partie
de l'objet modelant le travail a été prévu par la recherche de filet sémantique faite dans les
années 60 (Quillian 1968). Une fois que le filet sémantique est construit, une technique
appelée l'activation de propagation est employée pour voir comment deux concepts ou
noeuds sont connexes.
Une exécution moderne d'un filet sémantique est l'utilité de la connaissance (KnU)
développée par IBM. KnU est la technologie site Web derrière Aqui'
(http://www.ibm.aqui.com). Plus que juste un filet sémantique, KnU établit un filet attribué,
où chaque utilisateur fait tracer ses propres préférences sur le filet sémantique fondamental.
Ceci permet des vues personnalisées du contenu et des concepts codés dans le filet
sémantique. Par exemple, une personne peut être au noeud de concept de Java et avoir des
liens forts aux fournisseurs gastronomes de café, alors que des autres peuvent avoir des liens
forts aux fournisseurs d'instrument de développement de Java.
LY_SII __ 66 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Tandis que non évidentes au premier regard, des armatures et les filets sémantiques sont très
étroitement liés à la logique d'attribut. Russell et Norvig (1995) fournissent un algorithme
pour transformer les deux représentations en logique de premier ordre. La différence
principale entre ces représentations de connaissance est leur syntaxe. Certains préfèrent la
logique formelle, alors que d'autres peuvent rapporter plus facilement aux représentations
graphiques.
Représentation de l'incertitude
Dans presque aucune application réelle, un système de raisonnement n'aura pas toutes les
informations importantes qu'il doit résoudre un problème a priori. Nous avons l'incertitude.
Dans la plupart des cas, il y aura quelques informations disponibles, mais le repos devra être
impliqué ou rassemblé pendant qu'inferencing procède. Heureusement, nous avons une
théorie statistique qui fonctionne bien dans des conditions de l'incertitude, appelées théorème
de Bayes le' règle ou Bayes'.
La probabilité de quelque chose peut s'étendre d'une probabilité de 0.0 (aucune chance) à une
probabilité de 1.0 (certitude). Les statisticiens différencient entre deux genres de probabilités.
D'abord, il y a des probabilités sans conditions (ou antérieures) qui représentent la chance que
quelque chose se produira. Par exemple, nous pouvons regarder dans un almanach de temps et
voir que, en moyenne, il a plu 10 jours en mars au Minnesota au cours des cent dernières
années. Ainsi la probabilité qu'il pleuvra n'importe quel jour donné en mars est
approximativement 33 pour cent. C'est la probabilité antérieure ou sans conditions.
Cependant, supposer que nous savons qu'un grand orage souffle dedans du Dakota du Sud, et
il atteindra le Minnesota demain. Étant donné que la connaissance, nous peut indiquer il y a
un risque de 80 pour cent de pluie. La probabilité à long terme a-t-elle changé ? Non ; mais
nous avons une évidence qui demain pourrait être un jour pluvieux, ainsi nous nous servons
de cette évidence pour mettre à jour notre prévision. Les statisticiens appellent ce type
d'évaluation de probabilité une probabilité conditionnelle, exprimé comme P (H | E), celui est
lu comme probabilité de l'hypothèse H étant donné que nous avons observé l'évidence E.
Théorème de Bayes le' indique que nous pouvons calculer la probabilité conditionnelle que
l'événement Y se produira étant donné que l'événement X déjà produit, étant donné que nous
sachions les probabilités antérieures que X et Y pourraient se produire, et la probabilité
conditionnelle que X se produira quand nous savons que Y s'est déjà produit.
P (Y | X) = P (X | Y) P (Y)/P (X)
Jusqu'ici, nous avons discuté la logique d'attribut, les armatures, et les filets sémantiques, et
avons montré comment ils peuvent représenter la connaissance. Puisque les partisans des
diverses techniques ne pourraient pas convenir sur un format de représentation de
connaissance pour leurs applications d'AI, un besoin clair a été identifié d'un langage commun
d'établir les liens.
Le format d'échange de la connaissance est une langue qui a été expressément conçue pour
l'échange de la connaissance entre les agents (Gensereth et Fikes 1992). Basé sur la logique
d'attribut, KIF est une langue flexible de représentation de connaissance qui soutient la
définition des objets, des fonctions, des relations, des règles, et de la métaconnaissance (la
connaissance au sujet de la connaissance). En ces dernières années, KIF a émergé comme la
langue preferred dans les efforts d'avoir un format standard de représentation de connaissance
pour l'usage entre une série d'agents intelligents.
La syntaxe de langue de KIF est réminiscente de blèsent, qui n'est pas étonnante donnée sa
base de logique d'attribut. À la différence de blèsent cependant, KIF ne sont pas censés être un
langage de programmation. Ni est il a signifié pour être employé comme représentation de
connaissance interne. KIF a été explicitement conçu pour fournir un format commun pour
échanger l'information. KIF est puissant et assez expressif pour soutenir les conditions d'une
large variété de programmes d'AI. Indépendamment des représentations de connaissance
internes, tant que chaque programme peut lire et écrire KIF, la connaissance est portative et
réutilisable dans beaucoup de différents contextes. KIF est formellement défini et est le
résultat de plusieurs années d'effort par la connaissance de Defense Advanced Research
Projects Agency partageant l'équipe de travail d'environnement. La syntaxe de KIF peut être
coupée en trois groupes importants : variables, opérateurs, et constantes.
KIF soutient deux types de variables, les différentes variables qui commencent par ?
caractère, et variables d'ordre qui commencent par @ un caractère. Les quatre types
d'opérateurs incluent des opérateurs de limite, des opérateurs de règle, des opérateurs de
phrase, et des opérateurs de définition. Si une marque n'est pas une variable ou un opérateur,
alors ce doit être une constante. KIF fournit des distinctions pour plusieurs différents types de
constantes. Tous les nombres, caractères, et cordes sont des constantes de base dans KIF. Les
constantes d'objet dénotent des objets, les constantes de fonction dénotent des fonctions au-
dessus des objets, les constantes de relation dénotent des relations, et les constantes logiques
expriment des conditions booléennes au sujet du monde qui doit être vrai ou faux.
La langue soutient quatre types d'expressions : limites, phrases, règles, et définitions. Les
limites dénotent des objets, les phrases représentent des faits, les règles représentent des
étapes légales d'inferencing, et des définitions sont employées pour définir des constantes. Des
phrases se composent des constantes, des limites, et d'autres phrases. KIF définit en avant (des
lieux suivis de conséquent) et des règles d'inverse (conséquent suivi des lieux).
Une forme dans KIF est une phrase, une règle, ou une définition. Et en conclusion, une base
de connaissance de KIF est un ensemble fini de formes. L'ordre des formes dans une base de
connaissance n'est pas important.
les moyens « obtiennent le cours des actions d'actions et le placent dans la variable ?le prix,
examinent alors pour voir si le prix est plus grand que 150. »
Une règle complexe peut être presque illisible (aucune offense prévue pour bléser des
programmeurs) :
Ceci nous amène à la fin de notre examen des formats de représentation de connaissance.
Nous pouvons employer le code procédural, logique d'attribut, si puis des règles, des filets
sémantiques, ou des armatures pour représenter des faits, des règles, des rapports, et des
transformations complexes. Ces divers genres de représentations de connaissance peuvent
coder la connaissance au sujet de presque n'importe quel domaine de problème. Une fois
combinée avec un moteur de système ou d'inférence de raisonnement, une base de
connaissance devient une partie d'un système à base de connaissances, la dernière matière en
ce chapitre.
Maintenant que nous avons décrit beaucoup de types de connaissance que nous voulons
représenter, nous devons la grouper toute ensemble dans un endroit, dans notre base de
connaissance. La base de connaissance est le dépôt central d'information contenant les faits
que nous connaissons des objets et leurs rapports. C'était seulement après plusieurs années de
recherche d'AI qu'il est apparu clairement que la connaissance était la clef aux systèmes
LY_SII __ 69 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
réussis du bâtiment AI. Tout les travail sur des algorithmes de recherche et des méthodes de
résolution des problèmes générales a prouvé que sans connaissance profonde du domaine de
problème, n'importe quel problème réaliste bientôt sorti des limites des techniques standard de
recherche.
En même temps, les chercheurs d'intelligence artificielle sont devenus intéressés par des
techniques d'étude de machine. Using des données historiques des bases de données ou des
exemples produits par des experts, des réseaux neurologiques ont pu être formés pour
effectuer des tâches de classification et de prévision sans passer par le procédé d'acquisition
cher de la connaissance. Ces réseaux experts, car ils s'appellent, ont exécuté comme les
systèmes basés sur les règles dans beaucoup de cas soigneusement ouvrés. Ceci a stimulé un
intérêt remplacé pour les systèmes adaptatifs qui continue aujourd'hui.
d'entrée et les champs de rendement sont identifiables. Les états internes et le traitement sont
le résultat d'un procédé adaptatif de « étude » ou de « formation » où des données sont
présentées au réseau neurologique et les poids de raccordement sont automatiquement ajustés
par l'intermédiaire d'un algorithme d'étude.
Cependant, quoique des réseaux neurologiques ne puissent être facilement convertis en forme
symbolique, ils sont le plus certainement une base de connaissance, parce qu'ils codent la
connaissance implicite dans les données de formation. Nous regardons les réseaux
neurologiques et l'étude en plus détail en chapitre 5.
Résumé
Exercices
Chapitre 4
Systèmes &du Reasoning
En ce chapitre, nous nous concentrons sur la façon dont les diverses
représentations de connaissance présentées en chapitre 3 peuvent être employées
pour le raisonnement. Nous mettons en application un Java applet Qui emploie
en avant et vers l'arrière-enchaînant des algorithmes pour traiter si puis des
règles. Le traitement de logique floue et de règle sont également décrits. En
conclusion, nous explorons plusieurs techniques d'intelligence artificielle utilisées
pour la planification, y compris la planification de pile de but, la planification
non linéaire, et la planification hiérarchique.
Si alors les règles sont devenues la forme la plus populaire de représentation de connaissance
déclarative utilisée dans des applications d'intelligence artificielle. Il y a plusieurs raisons de
ceci. La connaissance a représenté comme si alors les règles est facilement compréhensible.
La plupart des personnes contrastent des règles confortables de lecture, avec la connaissance
représentée dans la logique d'attribut. Chaque règle peut être regardée comme morceau
autonome de la connaissance ou d'unité d'information dans une base de connaissance. De
nouvelles connaissances peuvent être facilement ajoutées, et la connaissance existante peut
être changée simplement en créant ou en modifiant différentes règles.
Des règles sont facilement manoeuvrées par les systèmes de motif. L'enchaînement vers
l'avant peut être employé pour produire de nouveaux faits (par conséquent les règles de
« production » de terme), et l'enchaînement en arrière peut déduire si les rapports sont vrais
ou pas. Les systèmes basés sur les règles étaient l'un des premiers succès commerciaux à
grande échelle de la recherche en matière d'intelligence artificielle. Un système expert ou le
système à base de connaissances est le terme commun employé pour décrire un système de
traitement basé sur les règles. Il se compose de trois éléments importants, une base de
connaissance (l'ensemble de si puis des règles et des faits connus), une mémoire temporaire
de travail ou une base de données des faits et des données dérivés, et un moteur d'inférence,
qui contient la logique de raisonnement employée pour traiter les règles et les données.
Avant que nous entrions dans les détails des motifs avec des règles, regardons une règle
simple :
fait joindre deux clauses antécédentes par une conjonction (num_wheels = 4 et moteur = oui)
et a une clause conséquente simple (vehicleType = automobile). Une règle énonce un rapport
entre les clauses (des affirmations ou des faits) et, selon la situation, peut être employée pour
produire de la nouvelle information ou pour prouver la vérité d'une affirmation. Par exemple,
si nous savons qu'un véhicule a quatre roues et un moteur, alors, using la règle ci-dessus, nous
pouvons conclure que le vehicleType est une automobile et ajouter cette base de fait à notre
connaissance. D'une part, si nous essayons de montrer que le vehicleType est une automobile,
nous devons découvrir si le véhicule a quatre roues et un moteur. Dans le premier cas, nous
LY_SII __ 73 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
sommes enchaînement vers l'avant, using des faits et des règles pour dériver de nouveaux
faits. Dans le deuxième cas, nous sommes enchaînement en arrière, essayant de prouver une
affirmation dans la conséquence d'une règle en prouvant que les clauses antécédentes sont
vraies.
Une règle dont les clauses antécédentes sont toutes vraies serait déclenchée ou préparent pour
mettre le feu. Nous mettons le feu à une règle déclenchée en affirmant la clause conséquente
et en l'ajoutant comme fait à notre mémoire temporaire de travail. À tout moment, une base de
règle peut contenir plusieurs règles qui sont prêtes à mettre le feu. Elle est jusqu'à la stratégie
de commande du moteur d'inférence à décider lesquels obtient mis le feu. Nous discuterons ce
point en plus détail plus tard en ce chapitre.
La plupart des systèmes basés sur les règles permettent à des règles d'avoir des noms ou des
étiquettes telles que Rule1 : ou automobile : pour identifier facilement des règles pour éditer
ou pour tracer pendant inferencing. Quelques systèmes permettent des disjonctions (ou) entre
les clauses antécédentes. C'est une sténographie qui réduit la taille d'une base de règle. Par
exemple :
La règle 3 a pu remplacer la règle 1 et la règle 2 dans la base de règle. La plupart des systèmes
de règle permettent également les opérateurs booléens de condition comme <, >, et !=, en plus
de l'égalité. Nous pourrions récrire la règle 3 sans employer des disjonctions :
Cela indique si les prévisions météorologiques indiquent que la pluie est probable avec une
probabilité au-dessus de 80 pour cent, alors nous soyons de 90 pour cent de certains qu'il
pleuvra. Si nous avons peu de confiance dans notre service local de prévision de temps, nous
pouvons abaisser le facteur de certitude de la règle à 50 pour cent.
Beaucoup de systèmes basés sur les règles permettent à des fonctions de s'appeler des clauses
antécédentes. Ces fonctions s'appellent les sondes, parce qu'elles sortent du moteur d'inférence
et examinent une certaine condition dans l'environnement. Les sondes renvoient
LY_SII __ 74 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
habituellement des valeurs booléennes, mais elles peuvent également renvoyer des données
ou des faits à la mémoire temporaire de travail. Quand on permet des fonctions dans le
conséquent, elles s'appellent les effecteur, qui augmentent considérablement les possibilités du
système basé sur les règles. Un effecteur transforme une règle d'un mécanisme fait-produisant
en dispositif action-produisant. Ces règles d'action permettent aux agents intelligents de faire
des choses pour nous. Par exemple, un agent intelligent qui traite l'email pourrait contenir la
règle suivante :
là où mailArrived et le processMail sont définis car les fonctions qui se connectent par
interface au système d'email, et la sonde () et l'effecteur () sont des méthodes données par le
système inferencing pour appeler ces fonctions.
Dans de petits nombres, les règles peuvent en juste proportion représenter beaucoup de types
de connaissance de domaine. Cependant, pendant que le nombre de règles se développe, les
aspects intuitifs de si alors des règles sont diminuées, et eux perdent leur efficacité d'une
perspective de lisibilité. Les systèmes commerciaux de règle-base laissent souvent grouper ou
diviser des règles de sorte qu'ils puissent être traités en tant que blocs logiques de la
connaissance afin d'essayer de surmonter cette faiblesse.
Un autre problème commun dans les systèmes basés sur les règles est que car l'information
plus complète entre, ou pendant que les choses changent dans le monde extérieur, les règles
qui ont pu avoir été vraies avant devenu fausses. La conséquence est que nous pouvons devoir
« rapporter » certains des « faits » qui ont été produits par les règles. Par exemple, si nous
voyons que l'herbe est humide, nous pouvons mettre le feu à une règle qui la conclut pleut.
Cependant, nous pouvons alors obtenir l'information que le système d'arrosage est allumé.
Ceci peut nous faire rétracter notre affirmation qu'il pleut ou abaisser au moins notre
confiance ou certitude en faisant cette conclusion. Ce problème de traiter des changements et
de rétracter des faits ou des affirmations s'appelle le raisonnement non monotonique.
Maintenir une règle-base conformée en contrôlant des dépendances entre les faits impliqués
exige un système de maintenance de l'intégrité. La plupart des systèmes de raisonnement, tels
que la logique d'attribut, sont monotoniques, c.-à-d., ils ajoutent l'information mais ne
rétractent pas l'information de la base de connaissance.
Dans les deux prochaines sections nous explorons le raisonnement vers l'avant et en arrière
avec des règles. Dans les deux sections, nous emploierons une base de règle simple comme
exemple. Cette base de règle devrait être familière. Nous avons décrit certaines des relations
en chapitre 3 quand nous avons discuté des armatures et des filets sémantiques. Nous
l'appelons la base de règle de véhicules (le schéma 4.1). Il a seulement neuf règles et sept
variables, avec une variable intermédiaire. Sept des règles définissent le genre de véhicule, et
deux sont employés pour déterminer si le véhicule est un cycle ou une automobile. La brièveté
et la clarté de cette petite règle-base nous aideront à se concentrer sur les questions liées à
inferencing basé sur les règles, et à ne pas obtenir si tout va bien distraits par les détails d'un
domaine plus complexe de problème.
Notre domaine de véhicules peut identifier trois types de cycles (un avec un moteur et deux en
dehors) et sept types d'automobiles. Nous différencions des cycles en tant qu'ayant plus moins
de quatre roues, et automobiles en tant qu'ayant exactement quatre roues et un moteur. Les
LY_SII __ 75 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
divers types d'automobiles sont identifiés par leur taille relative et le nombre de portes qu'ils
ont.
Plusieurs outils commerciaux ont été développés principalement pour faire le raisonnement de
chaînage avant. La langue OPS5, et les OPS83 augmentés postérieurs, ont été développés à
l'université de carnegie-mellon. OPS5 a été employé pour mettre en application le système
R1. IBM a développé KnowledgeTool et TIR (le système Integrated de raisonnement), qui
étaient principalement des outils de chaînage avant. En plus de fournir les possibilités de
raisonnement, ces systèmes commerciaux ont également fourni plusieurs différentes stratégies
de commande et la capacité de se mélanger en code procédural de programme, effectivement
donnant la sonde et les possibilités d'effecteur.
Plus tard, nous allons mettre en application un système de chaînage avant, mais d'abord, nous
avons laissés regarder le processus de raisonnement en plus détail. Comme mentionné avant,
n'importe quel système expert exige trois éléments de base, une base de connaissance des
règles et des faits, une mémoire temporaire de travail pour stocker des données pendant
inferencing, et un moteur d'inférence. Les étapes suivantes font partie du cycle de chaînage
avant :
1. Charger la base de règle dans le moteur d'inférence, et tous les faits de la base de
connaissance dans la mémoire temporaire de travail.
3. Assortir les règles contre les données dans la mémoire temporaire de travail et déterminer
quelles règles sont déclenchées, signifiant que toutes leurs clauses antécédentes sont vraies.
Cet ensemble de règles déclenchées s'appelle l'ensemble de conflit.
LY_SII __ 76 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
4. Employer le procédé de résolution du conflit pour choisir une règle simple de l'ensemble
de conflit.
5. Mettre le feu à la règle choisie en évaluant les clauses conséquentes ; l'une ou l'autre mise
à jour la mémoire temporaire de travail si c'est une règle fait-produisante, ou appellent le
procédé effecteur, si c'est une règle d'action. Ceci désigné sous le nom de l'étape d'acte.
Pendant la phase d'allumette de l'enchaînement vers l'avant le système d'inférence compare les
faits ou la mémoire temporaire de travail connus contre les clauses antécédentes dans les
règles pour déterminer quelle règle ou règles pourraient mettre le feu. Dans une base de
connaissance avec beaucoup de faits et de règles, la phase d'allumette peut prendre une
énorme quantité de durée de la transformation. Ainsi, nous voudrions examiner seulement ces
règles dont les clauses antécédentes se rapportent aux faits qui ont été mis à jour par la mise à
feu de la règle antérieure. L'algorithme de Rete, développé pour la langue OPS5, établit une
structure de données de réseau pour contrôler les dépendances entre les données, la condition
examine, et des règles, et réduit au minimum le nombre d'essais exigés pour chaque opération
d'allumette (Forgy 1982). Tandis que l'algorithme de Rete est Cadillac des algorithmes
d'allumette, beaucoup de systèmes de chaînage avant emploient les méthodes qui sont moins
efficaces mais plus faciles pour mettre en application.
Une fois que nous avons fini la phase d'allumette et avons produit l'ensemble de conflit, nous
nous déplaçons à l'étape de résolution du conflit. La résolution du conflit est peut-être l'étape
la plus importante en termes de comportement du système inferencing de chaînage avant.
Quand l'ensemble de conflit est vide ou contient seulement une règle simple, le problème est
insignifiant. Cependant, dans beaucoup de cas, il y aura plus d'une règle qui est déclenchée.
Quelle règle choisissons-nous pour mettre le feu ? Plusieurs solutions de rechange sont
disponibles :
• Choisir la première règle dans l'ensemble de conflit. C'est certainement simple, et pour
quelques domaines cela fonctionne.
• Choisir la règle qui se rapporte aux données qui ont changé récemment. Cette méthode
exige que les changements à la mémoire temporaire de travail sont horodatés ou de façon
ou d'autre étiquetés pour montrer quand ils étaient Last modified.
• Si la règle a mis le feu sur le cycle précédent, ne pas l'ajouter à l'ensemble de conflit. Cette
règle est parfois prolongée aux règles de limite ainsi ils peuvent seulement mettre le feu une
fois.
• Dans les cas où il y a une cravate, choisir une règle aléatoirement de ce sous-ensemble de
l'ensemble original de conflit.
LY_SII __ 77 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Une stratégie de commande commune dans les systèmes basés sur les règles est d'assigner des
priorités aux règles qui peuvent être employées pour faciliter le processus de sélection. Si
nous avons un processus qui procède en trois phases, nous pouvons assigner la priorité 1 à
l'ensemble de règles qui contribuent à la première phase, la priorité 2 aux règles dans la
deuxième phase, et de même pour le troisième sous-ensemble de règles. L'avantage
d'employer des priorités est qu'il réduit considérablement le nombre de règles qui doivent être
recherchées et examinées dans la phase d'allumette.
Une autre approche qui peut être employée pour réaliser les mêmes résultats, même si le
système inferencing ne soutient pas formellement des priorités, est d'employer des clauses de
garde. Par exemple, nous pourrions ajouter une priorité de clause = 1 aux antécédents de
toutes les règles dans le groupe un, priorité = 2 dans le groupe deux et ainsi de suite. Tandis
que moins efficace que si les priorités inferencing de soutiens de système, il produit le
comportement désiré.
Dans cette section, nous jetons un coup d'oeil à un exemple simple de l'enchaînement vers
l'avant dans notre domaine de véhicule. Pour commencer, nous chargeons notre base de règle
de véhicule dans le moteur d'inférence et définissons un ensemble de valeurs initiales pour des
variables dans la mémoire temporaire de travail :
num_wheels=4
motor=yes
num_doors = 3
size=medium
Après, nous faisons une phase d'allumette, où nous examinons les clauses antécédentes de
chaque règle pour déterminer lesquels peuvent être déclenchés. Nous n'avons aucune valeur
pour le vehicleType, ainsi les sept premières règles ne sont pas déclenchées. Les deux
dernières règles exigent des valeurs pour des num_wheels et circulent en voiture, ainsi elles
sont des candidats. Les num_wheels < clause 4 dans le cycle : la règle est fausse, de sorte que
ne soit pas déclenché, mais les num_wheels = 4 et moteur = sont oui rectifient et ainsi la règle
d'automobile est déclenchée. Notre ensemble de conflit de notre premier cycle d'allumette
contient une règle simple, l'automobile : règle.
Automobile: IF num_wheels=4
AND motor=yes
THEN vehicleType=automobile
La résolution du conflit est facile : Nous choisissons la règle simple et lui mettons le feu dans
le cycle d'acte. Mise à feu de l'automobile : ordonner les causes nous pour lier la valeur
LY_SII __ 78 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
num_wheels=4
motor=yes
num_doors = 3
size=medium
vehicleType=automobile
Maintenant nous sommes prêts pour notre prochain cycle inferencing. Nous faisons une
allumette contre les règles pour déterminer lesquels pourraient être mis le feu. Maintenant que
le vehicleType a une valeur, les sept premières règles sont des candidats. Cependant, les trois
premières règles exigent ces vehicleType = cycle, qui est faux. Ceci laisse les quatre
prochaines règles : SportsCar, berline, monospace, et SUV. Seulement une règle simple a
toutes ses clauses antécédentes satisfaites, le monospace : ordonner avec des num_doors = 3
et taille = milieu. De nouveau, notre ensemble de conflit a seulement une règle simple dans
lui :
MiniVan: IF vehicleType=automobile
AND size=medium
AND num_doors=3
THEN vehicle=MiniVan
num_wheels=4
motor=yes
num_doors = 3
size=medium
vehicleType=automobile
vehicle=MiniVan
Nous faisons encore une autre phase d'allumette et constatons que seulement une règle est
déclenchée encore, le monospace : règle. Cependant, parce qu'elle a déjà mis le feu, nous ne
l'ajoutons pas à l'ensemble de conflit. Notre ensemble de conflit est maintenant vide, ainsi
nous arrêtons notre chaînage avant inferencing. Dans cet exemple, nous avons commencé par
quatre faits et avons calculé deux nouveaux faits, déterminant que le véhicule est un
monospace.
Enchaînement en arrière
L'enchaînement en arrière est employé pour les systèmes experts consultatifs, où les
utilisateurs posent des questions et obtiennent ont posé de principales questions trouver une
réponse. Un système expert tôt célèbre, Mycin, enchaînement en arrière utilisé pour exécuter
des diagnostics des infections bactériennes dans les patients médicaux (Shortliffe 1976).
1. Charger la base de règle dans le moteur d'inférence, et tous les faits de la base de
connaissance dans la mémoire temporaire de travail.
4. Trouver l'ensemble de règles qui se rapportent à la variable de but dans une clause
conséquente. C'est-à-dire, trouver toutes les règles qui placent la valeur de la variable de but
quand elles mettent le feu. Mettre chaque règle sur la pile de but.
7. Essayer de s'avérer que la règle est vraie en examinant toutes les clauses antécédentes
pour voir si elles sont vraies. Nous examinons chaque clause antécédente à leur tour : (a) Si la
clause est vraie, continuer à la prochaine clause antécédente. (b) Si la clause est fausse, alors
sauter la règle outre de la pile de but ; passer à l'étape 5. (c) si la valeur de vérité est
inconnue parce que la variable antécédente est inconnue, passent à l'étape 4, avec la
variable antécédente comme nouvelle variable de but. (d) Si toutes les clauses antécédentes
sont vraies, mettre le feu à la règle, plaçant la variable conséquente à la valeur conséquente,
bruit la règle outre de la pile de but, et aller à 5.
MiniVan: IF vehicleType=automobile
LY_SII __ 80 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
AND size=medium
AND num_doors=3
THEN vehicle=MiniVan
Nous commençons par une mémoire temporaire de travail vide. Aucun fait n'est connu sur les
attributs de véhicule. La première chose que nous ferions est de vérifier la mémoire
temporaire de travail pour voir si le véhicule = le monospace est déjà vrai. Sinon, puis toutes
les clauses antécédentes du monospace : la règle doit être vraie pour conclure sans risque que
le véhicule est un monospace. En conséquence, nous devons essayer de prouver chaque clause
antécédente alternativement. La première chose que nous faisons est essai si le vehicleType =
l'automobile est vrai. La variable de vehicleType est n'a aucune valeur, ainsi nous recherchons
une règle qui a le vehicleType = l'automobile dans sa clause conséquente, et trouvons
l'automobile : règle ci-dessous :
Automobile: IF num_wheels=4
AND motor=yes
THEN vehicleType=automobile
num_wheels=4
motor=yes
vehicleType=automobile
Retournant à notre règle originale, nous savons maintenant que la première clause antécédente
est vraie. Nous devons après trouver des valeurs pour la taille et les num_doors. Using le
même processus décrit ci-dessus, nous finissons demander vers le haut à l'utilisateur ces
valeurs. L'utilisateur indique ces taille = milieu et num_doors = 3. Toutes les clauses
antécédentes ont été satisfaites, ainsi nous pouvons conclure que le véhicule est un
monospace. Notre mémoire temporaire de travail finale contient :
num_wheels=4
motor=yes
vehicleType=automobile
size=medium
num_doors=3
vehicle=MiniVan
LY_SII __ 81 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Tandis que notre petit exemple établi, dans beaucoup de cas la règle que nous essayons de
prouver n'est pas vrai. Nous pouvons devoir rechercher d'autres chemins par des règles
alternatives afin de répondre à la question de l'utilisateur. L'algorithme de vers l'arrière-
enchaînement exécute quelles quantités à une profondeur-première recherche par la base de
règle tout en essayant de prouver une clause de but.
Dans cette section, nous présentons un applet qui met en application les deux types principaux
d'algorithmes de raisonnement utilisés avec les systèmes basés sur les règles : enchaînement
vers l'avant et en arrière. L'applet de règle comporte trois carreaux des textes pour montrer la
base de règle, les variables et leurs valeurs courantes, et une trace du processus inferencing.
Le schéma 4.2 montre l'applet de règle.
Au dessus du dialogue, les utilisateurs peuvent choisir une des trois bases de règle
d'échantillon fournies, la base de règle de véhicule déjà discutée, une base de règle de bogues,
et les usines ordonnent la base. Les règles de la base choisie de règle sont montrées dans le
java.awt. Commande de TextArea au gauche supérieur. Vers la droite sont deux commandes
bien choisies de java.awt (boîtes de liste drop-down) qui permettent à l'utilisateur de
spécifier la variable et une valeur correspondante pour la variable choisie. Noter que la
variable et la valeur doivent être choisies pour que la variable soit changée. Toutes les fois
qu'une variable est changée, sa nouvelle valeur est ouverte une session la commande variable
de TextArea qui est immédiatement au-dessous des commandes bien choisies.
Près du fond du dialogue, deux commandes de bouton par radio permettent à l'utilisateur de
spécifier si l'enchaînement vers l'avant ou en arrière devrait être employé. Si l'enchaînement
en arrière est spécifié, le nom de la variable de but doit être écrit dans le but java.awt
TextField à la droite des boutons par radio.
Il y a trois boutons poussoirs au fond même du dialogue. L'extrême gauche est le but de
trouvaille, qui cause un cycle inferencing d'être exécuté. Ce cycle emploiera les arrangements
courants de variable-valeur. Après qu'un but de trouvaille soit exécuté, vous pouvez appuyer
sur le bouton de remise sur la droite inférieure. Ceci placera toutes les variables de règle-base
aux valeurs nulles. Quand le bouton moyen, démo courue, est cliqué, selon la base de règle et
méthode d'enchaînement choisie, les variables sera placé aux valeurs de préréglage, et un but
automatique de trouvaille est exécuté.
Notre exécution de Java inclut une classe de règle, une classe de RuleVariable, et une classe
de RuleBase, aussi bien que plusieurs classes de soutien telles que la clause. Nous
commençons notre discussion avec la classe de règle.
Règles
La classe de règle est employée pour définir une règle simple et contient également les
méthodes qui soutiennent le processus inferencing. Chaque règle a un membre nommé de
données, une référence à l'objet de possession de RuleBase (décrit plus tard), un choix de
clauses antécédentes, et une clause conséquente simple. La valeur de vérité de la règle est
LY_SII __ 82 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
stockée dans la vérité booléenne. La note, ceci est un objet booléen, pas une variable
booléenne élémentaire. Ceci nous permet d'employer une valeur nulle pour indiquer que la
vérité de la règle ne peut pas être déterminée (parce qu'une des variables référencées dans une
clause est également nulle ou non définie). Le membre booléen mis le feu indique si cette
règle a été mise le feu ou pas.
lhs2.addRuleRef(this) ;
antecedents[2] = lhs3 ;
lhs3.addRuleRef(this) ;
consequent = rhs ;
rhs.addRuleRef(this) ;
rhs.isConsequent() ;
rb.ruleList.addElement(this) ; // add self to rule list
truth = null ;
}
Rule(RuleBase Rb, String Name, Clause lhs1, Clause lhs2,
Clause lhs3, Clause lhs4,
Clause rhs) {
rb = Rb ;
name = Name ;
antecedents = new Clause[4] ;
antecedents[0] = lhs1 ;
lhs1.addRuleRef(this) ;
antecedents[1] = lhs2 ;
lhs2.addRuleRef(this) ;
antecedents[2] = lhs3 ;
lhs3.addRuleRef(this) ;
antecedents[3] = lhs4 ;
lhs4.addRuleRef(this) ;
consequent = rhs ;
rhs.addRuleRef(this) ;
rhs.isConsequent() ;
rb.ruleList.addElement(this) ; // add self to rule list
truth = null ;
}
Clauses
Des clauses sont employées dans les parties antécédentes et conséquentes d'une règle. Une
clause se compose habituellement d'un RuleVariable du côté à gauche, d'une condition, qui
examine l'égalité, plus grande que, ou moins que, et du côté droit, qui dans notre exécution est
une valeur (symbolique ou numérique) de corde. Par exemple la règle :
Automobile: IF num_wheels=4
AND motor=yes
sorte que toutes les fois que la valeur de variable est changée, la clause puisse être
automatiquement retestée. Le booléen conséquent est placé à faux, au commencement, parce
que la plupart des clauses sont des clauses antécédentes.
La classe de clause contient quatre méthodes. La méthode d'addRuleRef () est employée par
le constructeur de règle pour enregistrer la règle avec cette clause. La méthode de contrôle ()
réalise un essai de la clause. Si la clause est employée comme clause conséquente, alors l'essai
de sa valeur de vérité ne semble aucun raisonnable ; nous renvoyons une valeur nulle. Si la
variable du côté à gauche est non liée, nous renvoyons également la nulle, parce qu'une valeur
de vérité ne peut pas être déterminée. Si la variable est liée, nous employons le rapport de
commutateur pour examiner l'état logique spécifique et pour renvoyer la valeur de vérité en
résultant. L'isConsequent () renvoie les retours conséquents booléens et de getRule () de
méthode une référence à l'exemple de possession de règle.
Boolean check() {
if (consequent.booleanValue() == true) return null ;
if (lhs.value == null) {
return truth = null ; // var value is undefined
} else {
switch(cond.index) {
case 1: truth = new Boolean(lhs.value.equals(rhs)) ;
break ;
case 2: truth = new Boolean(lhs.value.compareTo(rhs) > 0) ;
break ;
case 3: truth = new Boolean(lhs.value.compareTo(rhs) < 0) ;
break ;
case 4: truth = new Boolean(lhs.value.compareTo(rhs) != 0) ;
break ;
}
return truth ;
}
}
La classe de condition est une classe d'aide à la clause. Elle prend une représentation de
corde d'un essai conditionnel et des convertis qui dans un code pour l'usage dans le rapport
de commutateur dans la méthode de Clause.check ().
Variables
Nous définissons une classe basse pour les variables qui soutiennent la fonction que nous
avons besoin pour le traitement de règle et pour apprendre dans le prochain chapitre. La classe
variable a un membre nommé pour identifier la variable, et un membre de valeur de corde
(qui pourrait être un objet dans une application plus d'usage universel). La colonne est
employée pour spécifier la position de la variable dans un fichier de données. Il y a un
constructeur de défaut, aussi bien qu'un où le nom est spécifié. Deux méthodes d'accédant
sont fournies pour placer la valeur et pour obtenir la valeur de la variable. Le membre
d'étiquettes est habitué pour tenir des symboles discrets pour des variables catégoriques. La
méthode de setLabels () est employée pour définir les valeurs symboliques valides pour des
variables catégoriques. La méthode de getLabel () renvoie la valeur symbolique pour l'index
spécifique et le getIndex inverse de méthode () renvoie l'index donné une valeur symbolique.
Un exemple de la façon dont ces méthodes sont employées est montré dans la section sur
l'exécution de base de règle de véhicule où les variables sont définies.
String name ;
LY_SII __ 86 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
String value ;
int column ;
public Variable() {} ;
public Variable(String Name) {name = Name; value = null; }
void setValue(String val) { value = val ; }
String getValue() { return value; }
Rule variables
Pour le traitement de règle, nous sous-classe notre classe variable et ajoutons un certain
comportement règle-spécifique. Il fournit l'appui nécessaire pour des variables utilisées dans
inferencing. Le constructeur prend le nom de la variable comme seul paramètre.
RuleVariables héritent du comportement symbolique discret de la classe variable basse. Un
nouveau membre de données est les clauseRefs de vecteur, qui tient des références à toutes
les clauses qui se rapportent à cette variable. Les exemples de la clause s'enregistrent en
appelant la méthode d'addClauseRef (). Il y a plusieurs méthodes qui sont dépassées comme
quelques neufs supplémentaires pour le traitement de règle. La méthode de setValue () place
non seulement la valeur de la variable, elle appelle également la méthode d'updateClauses (),
qui réitère par chaque clause qui se rapporte à ce RuleVariable et reteste sa valeur de vérité
par l'intermédiaire de sa méthode de contrôle ().
LY_SII __ 87 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
promptString stocke le texte qui est montré quand l'utilisateur est incité à fournir une valeur
pour cette variable. Le ruleName tient le nom de la règle qui a placé cette valeur de
RuleVariables ; quand les feux de règle il appelle la méthode de setRuleName () en
conséquence. La méthode d'askUser () appelle la méthode de waitForAnswer () sur le
RuleApplet. Ceci ouvre une zone de dialogue qui incite l'utilisateur à fournir une valeur pour
la variable pendant inferencing. Ceci est seulement employé par l'algorithme de vers l'arrière-
enchaînement.
void updateClauses() {
Enumeration enum = clauseRefs.elements() ;
while(enum.hasMoreElements()) {
((Clause)enum.nextElement()).check() ; // retest the clause
}
}
String promptString ; // used to prompt user for value
String ruleName ; // if value is inferred, null = user provided
void setRuleName(String rname) { ruleName = rname; }
...
};
Base de règle
String name ;
Hashtable variableList ; // all variables in the rulebase
Clause clauseVarList[];
Vector ruleList ; // list of all rules
Vector conclusionVarList ; // queue of variables
Rule rulePtr ; // working pointer to current rule
Clause clausePtr ; // working pointer to current clause
Stack goalClauseStack; // for goals (cons clauses) and subgoals
...
Notre exécution de chaînage avant emploie des méthodes dans la classe de RuleBase et la
classe de règle. La méthode de forwardChain () dans la classe de RuleBase contient la
logique de commande principale pour l'enchaînement vers l'avant. La méthode assigne
d'abord le vecteur de conflictRuleSet. La méthode d'allumette () s'appelle avec un paramètre
vrai booléen pour forcer un premier essai de toutes les règles dans la base de règle. Ceci
retourne avec le conflictRuleSet initial, un vecteur des règles qui sont déclenchées et pourrait
être mis le feu. Nous écrivons alors une boucle de moment (), qui fonctionne jusqu'à ce que
nous ayons un conflictRuleSet vide. À l'intérieur de la boucle, nous d'abord appel la méthode
de selectRule (), passant le conflictRuleSet comme paramètre. La méthode de selectRule ()
exécute la stratégie de résolution du conflit et revient avec une règle simple au feu. Nous
appelons la méthode de Rule.fire () pour effectuer la tâche conséquente de clause, et puis
retestons toutes les clauses et règles qui se rapportent à la variable mise à jour. Tandis que
pas une exécution de Rete, cette approche limite la quantité d'essai de clause qui doit être
exécutée. Avec le variableList mis à jour, nous appelons l'allumette () encore, mais cette fois
où nous passons en valeur fausse booléenne de paramètre. Ceci indique l'allumette () regarder
seulement les valeurs de vérité de règle, pour ne pas examiner chaque règle.
while(conflictRuleSet.size() > 0) {
La méthode de Rule.check () est employée pendant l'enchaînement vers l'avant pour examiner
les clauses antécédentes de la règle. Le cas échéant des clauses a une valeur de vérité non
définie, puis une valeur nulle est retournée par le contrôle (). Le cas échéant des clauses est
faux, puis la valeur de vérité de la règle est placée à faux et une valeur fausse est retournée. Si
toutes les clauses antécédentes sont vraies, alors la valeur de vérité de la règle est placée pour
rectifier, et une valeur vraie est retournée. Noter que seulement des conjonctions (et) sont
soutenus, pas des disjonctions (ou) entre les clauses.
La méthode de Rule.fire () est employée pendant l'enchaînement vers l'avant quand une règle
avec une véritable valeur de vérité est choisie être mise le feu. Le drapeau booléen mis le feu
est placé pour prouver que la règle a mis le feu. Le RuleVariable du côté à gauche de la
clause conséquente est placé à la valeur du côté droit. La méthode de checkRules () s'appelle
alors pour retester ces règles qui se rapportent à la variable conséquente.
La méthode de Rule.display () écrit l'éliminer dans une mise en forme de texte dans le
TextArea supérieur du RuleApplet. Ceci permet à l'utilisateur d'examiner le RuleBase pour
suivre une chaîne d'inférence.
• Si la règle était vraie prouvé, nous mettons le feu à la règle en fixant le but courant
variable à la valeur du côté droit du goalClause ; nous ajoutons une référence à la variable
pour lui dire quelle règle a produit sa valeur ; nous sautons la clause outre du
goalClauseStack et affichons un message de succès. Si le goalClauseStack est vide, nous
sommes enchaînement en arrière fait, ainsi nous affichons un message de victoire et
éclatons de la boucle.
while (goalClauses.hasMoreElements()) {
Clause goalClause = (Clause)goalClauses.nextElement() ;
if (goalClause.consequent.booleanValue() == false) continue ;
goalClauseStack.push(goalClause) ;
if (goalClauseStack.empty() == true) {
textArea1.appendText(“\n +++ Found Solution for goal: ”
+ goalVar.name);
break ; // for now, only find first solution, then stop
}
} else {
goalClauseStack.pop() ; // clear item from subgoal stack
textArea1.appendText(“\nRule ” + goalRule.name +
“ is false, can’t set ” + goalVar.name);
}
}
if (goalVar.value == null) {
textArea1.appendText(“\n +++ Could Not Find Solution for goal: ”
+ goalVar.name);
}
}
par la boucle entière, alors toutes les clauses antécédentes sont vraies, ainsi nous plaçons et
renvoyons vrai comme valeur de vérité de la règle.
Les six premières méthodes traitent des actions d'utilisateur sur le sélecteur bien choisi de
base de règle de trois commandes-le, le sélecteur variable, et la valeur sélecteur-et les trois
boutons-le trouvent, des boutons de démo de course, et de remise respectivement.
La méthode d'init () contient une section de code produite par le constructeur visuel visuel de
CafŽ pour initialiser les commandes d'awt d'applet. Au fond de la méthode d'init (), nous
instancions une armature pour être le parent du RuleVarDialog, initialisons la commande
bien choisie de base de règle, et puis instancions et initialisons les trois objets de RuleBase
d'exemple. () La méthode handleEvent conduit les actions d'utilisateur aux méthodes de
événement-manipulation appropriées. Noter que c'est modèle de événement-manipulation de
Java 1.0.2. Le modèle d'événement de Java 1.1 est très différent, mais Symantec n'a pas eu le
soutien de Java 1.1 quand nous avons écrit ce code. Après, les commandes d'awt sont
assignées par code produit CafŽ, et nous fournissons des variables statiques de membre pour
tenir notre armature et exemples de RuleBase. Le membre de currentRuleBase indique
toujours la base choisie de règle dans la commande choice1.
/* RuleApplet class
*/
import java.awt.*;
import java.applet.*;
import java.util.* ;
RuleVariable rvar =
(RuleVariable)currentRuleBase.variableList.get(varName);
Enumeration labels = rvar.labels.elements();
while (labels.hasMoreElements()) {
choice3.addItem(((String)labels.nextElement())) ;
}
}
// user selected a value for a variable
void choice3_Clicked(Event event) {
String varName = choice2.getSelectedItem() ;
String varValue = choice3.getSelectedItem() ;
RuleVariable rvar =
(RuleVariable)currentRuleBase.variableList.get(varName);
rvar.setValue(varValue) ;
textArea3.appendText(“\n”+ rvar.name + “ set to ”+ varValue) ;
}
//{{CONNECTION
// Clear the text for TextArea
textArea1.setText(“”);
textArea2.setText(“”);
textArea3.setText(“”);
//}}
currentRuleBase.reset() ;
currentRuleBase.displayRules(textArea1);
currentRuleBase.displayVariables(textArea3) ;
}
label1.reshape(24,12,96,24);
add(label1);
choice1 = new java.awt.Choice();
add(choice1);
choice1.reshape(132,12,192,24);
Group1 = new CheckboxGroup();
radioButton1 = new java.awt.Checkbox(“Forward Chain”,
Group1, false);
radioButton1.reshape(36,396,156,21);
add(radioButton1);
choice3 = new java.awt.Choice();
add(choice3);
choice3.reshape(480,36,135,24);
label5 = new java.awt.Label(“Value”);
label5.reshape(480,12,95,24);
add(label5);
choice2 = new java.awt.Choice();
add(choice2);
choice2.reshape(336,36,137,24);
textArea3 = new java.awt.TextArea();
textArea3.reshape(336,72,276,122);
add(textArea3);
label4 = new java.awt.Label(“Variable”);
label4.reshape(336,12,109,24);
add(label4);
radioButton2 = new java.awt.Checkbox(“Backward Chain”,
Group1, false);
radioButton2.reshape(36,420,156,24);
add(radioButton2);
textField1 = new java.awt.TextField();
textField1.reshape(324,420,142,27);
add(textField1);
label3 = new java.awt.Label(“Goal”);
label3.reshape(324,384,80,30);
add(label3);
//}}
currentRuleBase.displayVariables(textArea3) ;
radioButton1.setState(true) ;
choice1_Clicked() ; // fill variable list
}
java.awt.TextField textField1;
java.awt.Label label3;
//}}
L'exécution de base de règle de véhicules la base de règle de véhicules est définie suivre la
méthode de RuleApplet.initVehiclesRuleBase (). L'exemple de RuleBase est passé dedans
comme seul argument. La méthode instancie d'abord les membres de goalClauseStack et de
variableList. Chaque RuleVariable est alors défini en créant un exemple avec le nom
variable comme argument sur le constructeur. Les valeurs valides sont placées suivre la
méthode de setLabels (). Le texte prompt, utilisé dans le RuleVarDialog pendant
l'enchaînement en arrière, est placé suivre la méthode de setPromptText (). Chaque
RuleVariable est également ajouté directement au variableList de RuleBase.
Après que toutes les variables soient définies, quelques exemples de condition ne sont créés
pour des égales, pas égales, et moins que. Le membre de ruleList est instancié, et chaque
règle dans le RuleBase est instanciée. Les constructeurs de règle prennent une référence de
RuleBase, la corde de nom de règle, et deux clauses ou plus. La dernière clause est la clause
conséquente et toutes les clauses antérieures sont des clauses antécédentes.
LY_SII __ 100 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
rb.variableList.put(vehicle.name,vehicle) ;
RuleVariable vehicleType = new RuleVariable(“vehicleType”) ;
vehicleType.setLabels(“cycle automobile”) ;
vehicleType.setPromptText(“What type of vehicle is it?”) ;
rb.variableList.put(vehicleType.name, vehicleType) ;
// define rules
rb.ruleList = new Vector() ;
Rule Bicycle = new Rule(rb, “bicycle”,
new Clause(vehicleType,cEquals, “cycle”) ,
new Clause(num_wheels,cEquals, “2”),
new Clause(motor, cEquals, “no”),
new Clause(vehicle, cEquals, “Bicycle”)) ;
rb.displayVariables(textArea2);
}
The RuleApplet.demoVehiclesBC() method is called when the vehicles rule base and the
backward chaining radio button are selected and the Run Demo pushbutton is clicked. The
vehicle and vehicleType variables are set to null, and the other variables are set to indicate that
the vehicle is a MiniVan. The variable value settings are displayed in the trace panel, the
RuleBase.backwardChain() method is called, and the resulting variable values are displayed
in the trace panel.
L'exécution des autres bases de deux règles équipées d'applet de règle, de bogues et de bases
de règle d'usines, est énumérée dans l'annexe A.
Cela apporte à une fin notre discussion de l'applet de règle. Tout les code décrit en ce chapitre
est inclus sur le disque compact-ROM. L'applet et les classes fondamentales de RuleBase, de
règle, et de RuleVariable fournissent la fonctionnalité de base. Quelques perfectionnements
LY_SII __ 103 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
évidents viennent à l'esprit. Ceux-ci incluent le soutien des objets du côté à gauche et droit
des clauses. Dans la classe de règle, il ferait beau de fournir l'appui pour les sondes et les
effecteur (qui pourraient être utiles dans la partie de ce livre). Le soutien des exemples
multiples des variables et du temps-estampillage des données prolongerait considérablement
les possibilités de chaînage avant. Ajouter des priorités de règle serait également utile pour de
plus grandes bases de règle. S'ajouter a augmenté la découverte et comment et pourquoi le
soutien de l'algorithme de vers l'arrière-enchaînement serait un contact gentil. Bien qu'il y ait
beaucoup plus nous pourrions faire, il est important d'identifier que même ce niveau de la
fonctionnalité est capable de produire le comportement utile dans les applications, ou car nous
verrons, dans les agents intelligents.
Dans le reste de ce chapitre, nous changeons notre foyer de l'exécution en discussion plus à
niveau élevé des systèmes brouillés et puis de la planification de règle. Des systèmes brouillés
de règle sont employés pour exécuter un genre d'enchaînement vers l'avant, mais le système
de logique fondamental est basé sur la logique floue, logique non booléenne. La planification
est une matière intéressante, parce que pour n'importe quoi autre que des tâches simples, nos
agents intelligents devront établir des plans et les exécuter afin d'effectuer le travail utile pour
nous.
Dans l'histoire riche du raisonnement basé sur les règles dans l'AI, les moteurs d'inférence
presque sans exception ont été basés sur la logique booléenne ou binaire. Cependant, de la
même manière ce les réseaux neurologiques ont enrichi le paysage d'AI en fournissant une
alternative aux techniques de traitement de symbole, logique floue a fourni une alternative
aux systèmes logique-basés booléens (Bigus 1996).
À la différence de la logique booléenne, qui a seulement deux affaires de logique floue d'états,
vraie ou fausse, avec les valeurs de vérité qui s'étendent sans interruption de 0 à 1. Ainsi
quelque chose pourrait être 0.5 à moitié vrai ou très probable rectifier 0.9 ou pas rectifier
probablement 0.1. L'utilisation de la logique floue dans des impacts de systèmes de
raisonnement non seulement le moteur d'inférence mais la représentation de connaissance lui-
même (Zadeh 1994). Pour, au lieu de faire des distinctions arbitraires entre les variables et les
états, comme est exigé avec des systèmes de logique booléenne, la logique floue permet à on
d'exprimer la connaissance en format de règle qui est proche d'une expression de langage
naturel. Par exemple, nous pourrions dire :
si la température est chaude et l'humidité est collante alors fan_speed est haute
La différence entre cette règle brouillée et les règles de Booléen-logique que nous avons
employées dans notre vers l'avant et le vers l'arrière-enchaînement des exemples est que les
clauses la « température est chaude » et la « humidité est collante » ne sont pas strictement
vraie ou fausse. Les clauses dans des règles brouillées sont des fonctions à valeurs réelles
appelées les fonctions d'adhésion qui tracent l'ensemble brouillé « chaud » sur le domaine de
la « température » variable brouillée et produisent une vérité-valeur qui s'étend de 0.0 à 1.0
(une valeur continue de rendement, tout comme les réseaux neurologiques).
Les motifs avec les systèmes brouillés de règle sont un procédé de chaînage avant. Les
valeurs de données numériques initiales fuzzified, c.-à-d., s'est transformé en valeurs
LY_SII __ 104 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
brouillées using les fonctions d'adhésion. Au lieu d'une phase d'allumette et de résolution du
conflit où nous choisissons une règle déclenchée pour mettre le feu, dans les systèmes
brouillés, à toutes les règles sont évalués, parce que toutes les règles brouillées peuvent être
vraies à un certain degré (s'étendant de 0.0 à 1.0). Les valeurs de vérité antécédentes de clause
sont combinées using des opérateurs de logique floue (une conjonction brouillée ou et
l'opération prend la valeur minimum des deux clauses brouillées). Après, les ensembles
brouillés spécifiques dans les clauses conséquentes de toutes les règles sont combinés, using
les valeurs de vérité de règle comme facteurs de cadrage. Le résultat est un ensemble brouillé
simple, qui defuzzified alors pour renvoyer une valeur croquante de rendement.
Planification
La planification est l'un des problèmes les plus complexes que l'AI a essayé de résoudre.
Cependant, elle est une des plus utile dans cela que la plupart des problèmes non triviaux
exigent un certain ordre commandé des opérations et d'une série de techniques. La
planification implique plusieurs aspects de la résolution des problèmes. Est d'abord la
décomposition d'un grand problème dans de plus petits, plus facilement résolus sous-
problèmes. En second lieu tient compte des contraintes sur l'ordre de la solution des sous-
problèmes de sorte que nous ne défassions pas le travail que nous avons effectué dans l'étape
précédente. Le bout est le défi de maintenir l'état du monde car nous progressons vers une
solution (Russell et Norvig 1995).
Un aspect important à se rappeler est que la planification n'est pas recherche. Nous n'essayons
pas simplement de traverser un graphique à la recherche d'un noeud simple de but ou de
trouver un chemin à un noeud de but. Dans la planification, nous calculons plusieurs étapes
d'une approche de résolution des problèmes sans les exécuter. En outre, il n'est parfois pas
possible de commencer au début et de procéder linéairement à une solution. Il peut y avoir des
discontinuités ou des coupures dans notre plan que nous ne pouvons pas surmonter. Par
exemple, comment obtenons-nous d'A à B quand il n'y a aucun chemin entre ces points ? Afin
de prévoir, nous devons avoir un modèle interne du monde de sorte que nous puissions
proposer des opérations et prévoir ce que seront les résultats, et s'ils nous amèneront plus près
du but ou pas.
La planification de pile de but était une tentative tôt à résoudre les problèmes qui pourraient
être divisés vers le haut en plus petits problèmes, et où il y avait des contraintes ou des
interactions entre les étapes dans le plan. Le problème de recherches s'est concentré sur un
monde de blocs, où le but était simplement d'arranger les blocs dans un ordre spécifique.
Tandis qu'apparemment insignifiant (âgé de deux ans peut faire la tâche), ce problème de
jouet illustrait des conditions essentielles pour des stratégies réussies de planification.
Donné une première configuration des blocs empilés sur l'un l'autre, ou se trouvant sur une
table, nous spécifions une configuration désirée de but. Nous avons un ensemble défini
d'opérateurs pour les blocs en mouvement, pour les prendre, pour les déplacer, ou pour les
empiler sur d'autres blocs. Notre plan est de développer l'ordre des opérateurs qui va de notre
état initial à notre état de but. La planification de pile de but, comme nom implique, emploie
une pile pour tenir des subgoals ou des buts intermédiaires que nous résolvons comme sous-
problèmes. Un problème majeur avec la planification de pile de but est que nous pouvons
déployer beaucoup d'effort résolvant des parties du problème tout en rendant d'autres pièces
plus difficiles, sinon impossible, pour résoudre. La faiblesse principale est que la planification
de pile de but essaye de résoudre le problème et les sous-problèmes linéairement, dans l'ordre,
et ne tient pas compte de comment l'ordre des actions peut effectuer le progrès vers l'objectif
ultime.
Plusieurs techniques non linéaires ont été développées afin d'éviter les problèmes avec des
techniques linéaires de planification telles que la planification de pile de but. Les approches
de planification non linéaires peuvent expliquer les interactions entre les opérateurs et les
subgoals. Elles construisent un plan où deux subgoals ou plus peuvent procéder
simultanément. Les systèmes non linéaires célèbres de planification d'AI incluent NOÉ
(Sacerdoti 1974) et MOLGEN (Stefik 1981). Une technique appelée la signalisation de
contrainte permet à des plans non linéaires d'être construits incrémentalement, avec un
ensemble d'opérateurs avec l'ordre incomplètement spécifique et les attaches variables. Plutôt
qu'appliquent un opérateur simple et puis mettent à jour l'espace comme dans la planification
ou la recherche du l'état-espace, la signalisation de contrainte permet les opérateurs multiples
et les attaches variables à spécifier dans un noeud simple.
L'analyse Means-ends est employée pour choisir des opérations le long de la manière. Chaque
opérateur a un ensemble de conditions préalables qui doivent tenir afin de l'opérateur pour
applicables, et un ensemble de postconditions qui spécifient les changements à l'état une fois
l'opérateur est appliqué. Ceci pré/la liste état de poteau vient à bout le problème d'armature
parce qu'il énonce explicitement quel sous-ensemble d'états doit se tenir et quel états seront
changés.
planification tenant compte seulement de ceux aux niveaux les plus élevés de la criticalité, et
procéder alors à une granularité plus fine et plus fine en ajoutant les opérateurs additionnels
pour satisfaire les conditions préalables aux niveaux plus bas. Tandis que l'arrangement
approprié des valeurs de criticalité est crucial, les planificateurs hiérarchiques se sont avérés
être l'une des techniques les plus pratiques pour des systèmes de planification.
Résumé
En ce chapitre nous nous sommes concentrés sur des techniques de raisonnement utilisées
avec si puis des règles. Les questions principales incluent :
• Si alors les règles sont les plus réussies former de la représentation de connaissance.
Il est facile pour des personnes créer et les comprendre.
• Une règle a deux parts, si ou partie antécédente, et la cloison puis ou conséquente.
Une condition dans la règle s'appelle une clause. Si toutes les clauses antécédentes
d'une règle sont vraies, elle est déclenchée pour mettre le feu. Quand les feux d'une
règle, sa clause conséquente est rendus vrais et un nouveau fait est ajouté à la base de
connaissance.
• Des facteurs de certitude ou de confiance sont employés comme modificateurs de
règle dans les situations où la validité des données ou l'applicabilité de la règle est
incertaine.
• Les systèmes de raisonnement sont monotoniques, signification qu'ils ajoutent
seulement jamais de nouveaux faits à la mémoire temporaire de travail, ou non
monotoniques, où ils peuvent rétracter des faits quand si avec la nouvelle évidence.
Les systèmes non monotoniques de raisonnement doivent traiter la maintenance de
l'intégrité, et les dépendances de voie entre les faits dans la mémoire temporaire de
travail.
• L'enchaînement vers l'avant est une méthode inferencing data-driven using des
règles. Commençant par un premier ensemble de faits dans la mémoire temporaire de
travail, la phase d'allumette choisit l'ensemble de conflit de règles qui sont prêtes à
mettre le feu. La résolution du conflit choisit une règle simple mettre le feu. La phase
d'acte met le feu à la règle et ajoute un nouveau fait à la mémoire temporaire de
travail. Ce processus est répété jusqu'à ce que l'ensemble de conflit soit vide.
• L'enchaînement en arrière est une méthode inferencing but-conduite using des
règles. Commençant par une variable ou une clause de but, les chaînes d'algorithme
par les règles des clauses conséquentes aux clauses antécédentes, essayant de prouver
la règle vraie.
• Nous avons mis en application un applet de règle qui emploie des classes de
RuleBase, de règle, et de RuleVariable pour effectuer l'enchaînement vers l'avant et en
arrière dans Java.
• Les systèmes brouillés sont des systèmes de règle qui emploient la logique floue
plutôt que la logique booléenne pour prendre des décisions.
• La planification est une condition fondamentale pour les agents intelligents. La
planification est difficile parce qu'il y a parfois des interactions entre les sous-
problèmes ou les morceaux du plan. Trois types importants d'algorithmes de
planification ont été étudiés. Ceux-ci incluent linéaire, non linéaire, et hiérarchique.
Exercices
LY_SII __ 107 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Chapitre 5
Systèmes du Learning
En chapitre 5, nous nous concentrons sur des techniques d'étude adaptatives de
logiciel et de machine. Nous commençons par une vue d'ensemble des différents
paradigmes pour effectuer l'étude de machine, y compris l'étude dirigée, non
surveillée, et de renfort. Nous fournissons une introduction générale aux réseaux
neurologiques et puis une discussion plus détaillée de la propagation arrière et
des cartes de Kohonen. Après, nous explorons l'utilisation de la théorie de
l'information de construire des arbres de décision des données. Nous concevons et
mettons en application un Java applet Et les classes de Java correspondantes
pour la propagation arrière, les cartes de Kohonen, et les algorithmes d'arbre de
décision. Durer, nous regardent les systèmes de classificateur, qui ajoutent l'étude
aux systèmes basés sur les règles using des algorithmes génétiques.
Vue d'ensemble
Il y a beaucoup de formes d'étude. D'abord, il y a étude par coeur, où un exemple est donné et
les copies d'étudiant (agent intelligent) l'exemple et reproduit exactement le comportement.
Tandis que l'étude par coeur est une forme simple d'étude elle peut encore être puissante. Par
exemple, nous pourrions courir une simulation 24 heures sur 24, 7 jours par semaine, pour
produire de nouvelles situations et du comportement désiré, puis présentons ces exemples à
notre agent. Notre agent pourrait mieux répondre aux situations pendant une semaine après
que nous avons commencé la formation et serait encore un meilleur un mois plus tard
(assumer la connaissance additionnelle n'a pas ralenti ses temps de réponse).
Une autre forme d'étude est ajustement de paramètre ou de poids. Dans ce cas-ci, nous
pouvons savoir a priori quels facteurs sont importants dans une certaine décision, mais nous
ne savons pas peser leur contribution à la réponse. Dans ce cas-ci, nous pouvons ajuster les
facteurs de pondération avec le temps de sorte que nous améliorions la probabilité d'une
décision correcte ou la produisions. Cette technique sert de base à l'étude de réseau
neurologique.
L'induction est un processus d'apprendre par exemple où nous essayons d'extraire les
caractéristiques importantes du problème nous permettant de ce fait de généraliser aux
LY_SII __ 109 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
situations ou aux entrées originales. Les arbres de décision et les réseaux neurologiques tous
les deux effectuent l'induction et peuvent être employés pour des problèmes de classification
ou de régression (prévision). L'aspect clé des méthodes inductives est que les exemples sont
transformés et automatiquement transformés en forme interne (représentation de
connaissance) qui capture l'essence du problème.
Le groupement est un autre algorithme d'étude, qui est un type de chunking. Les algorithmes
de groupement regardent les données haut-dimensionnelles (données avec beaucoup
d'attributs) et les marquent pour la similitude basée sur un certain critère. Le résultat est que
chaque échantillon est assigné à un faisceau ou à un groupe avec d'autres exemples considérés
pour être « semblable. » Cette similitude a pu être employée comme manière d'assigner la
signification à ce groupe d'échantillons. Par exemple, les données de groupement des clients
professionnels peuvent avoir comme conséquence quatre faisceaux distincts. L'examen des
clients qui sont tombés dans chaque faisceau peut les montrer qu'elles sont groupées basées
sur leurs intérêts (types de produit achètent) ou par leurs modèles acquéreurs (le nombre de
visites, ventes se monte, rentabilité) ou un autre critère ce qui ne peut pas avoir été évidente
en regardant les données originales. Un autre exemple grouperait des documents que nous
avons trouvés particulièrement utile. Ceci pourrait fournir des informations valables pour
améliorer l'exécution d'un Search Engine de document la prochaine fois que nous faisons une
question.
Tous ces techniques d'étude, induction pour la classification et prévision, et groupement sont
employés dans des outils d'exploitation de données. L'exploitation de données est un
processus d'extraire valable, l'information nonobvious de grandes collectes des données
(Bigus 1996). La contribution principale de l'exploitation de données à est des modèles de
trouvaille qui n'ont pas été connus pour exister, c.-à-d., pour découvrir la nouvelle information
ou connaissance (certains se réfèrent à l'exploitation de données comme découverte de la
connaissance). Ainsi apprenant, pour l'exploitation de données, peut être considéré pendant
qu'une manière pour que les agents intelligents découvrent automatiquement la connaissance
plutôt que l'ayant prédéfinissait using la logique d'attribut, les règles, ou une autre
représentation.
L'étude dirigée est la forme la plus commune d'étude et s'appelle parfois programmation par
exemple. L'agent de étude est formé en lui montrant des exemples de l'état de problème ou des
LY_SII __ 110 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
attributs avec le rendement ou l'action désiré. L'agent de étude fait une prévision basée sur les
entrées et si le rendement diffère du rendement désiré, alors l'agent est ajusté ou adapté pour
produire le rendement correct. Ce processus est répété à plusieurs reprises jusqu'à ce que
l'agent apprenne à faire des classifications ou des prévisions précises. L'étude dirigée est le
type le plus commun d'étude de machine. Les données historiques des bases de données, des
notations de sonde, ou des notations de trace sont employées souvent comme données de
formation ou d'exemple. Nous fournissons deux réalisations des algorithmes d'étude dirigés
plus tard en ce chapitre : le réseau neurologique de propagation arrière, et un arbre de
décision.
L'étude non surveillée est employée quand l'agent de étude doit identifier des similitudes entre
les entrées ou identifier des dispositifs dans les données d'entrée. Les données sont présentées
à l'agent, et elles s'adaptent de sorte qu'elles divisent les données dans des groupes. Le
processus de groupement ou de segmentation continue jusqu'à ce que l'agent place les mêmes
données dans le même groupe sur les passages successifs au-dessus des données. Un
algorithme d'étude non surveillé exécute un type de détection de dispositif où des attributs
communs importants dans les données sont extraits. Nous présentons une exécution de réseau
neurologique d'une technique d'étude non surveillée appelée une carte de Kohonen.
L'étude de renfort est un type de diriger apprenant où l'information d'erreur est moins
spécifique. Elle peut également être employée dans les cas où il y a un ordre des entrées et le
rendement ou la mesure est seulement pris après que l'ordre spécifique se produise. Puisque
nous fournissons moins d'informations spécifiques d'erreur, le renfort apprenant prend
habituellement plus longtemps l'étude que dirigée et est moins efficace. Cependant, dans
beaucoup de situations, avoir l'information préalable exacte au sujet des résultats désirés n'est
pas possible. De plusieurs manières, l'étude de renfort est la forme la plus réaliste d'étude.
Une autre distinction importante en apprenant des agents est si l'étude est en ligne ou en
différé fait. En ligne l'étude signifie que l'agent est envoyé pour effectuer ses tâches et qu'il
peut apprendre ou s'adapter après que chaque transaction soit traitée. En ligne l'étude est
comme la formation sur le tas et les conditions graves d'endroits sur les algorithmes d'étude.
Ce doit être très rapide et très écurie (nous ne voulons pas un agent en mort cérébrale au
milieu d'une grande négociation de ventes). L'étude en différé, d'une part, est plutôt une
conférence d'affaires. Vous prenez vos vendeurs outre du plancher et les placez dans un
environnement où ils peuvent se concentrer sur améliorer leurs qualifications sans
distractions. Après une période de formation appropriée, elles sont envoyées pour appliquer la
leur connaissance récemment découverte et qualifications. Dans un contexte d'agent
intelligent, ceci signifie que nous des données de rassemblement des situations que les agents
ont éprouvées. Nous pourrions alors augmenter ces données avec des informations sur la
réponse désirée d'agent pour établir un ensemble de données de formation. Une fois que nous
avons cette base de données nous pouvons l'employer pour modifier le comportement de nos
agents.
Réseaux neurologiques
Les réseaux neurologiques fournissent une manière simple d'ajouter la capacité d'étude aux
agents. Il y a beaucoup de différents types des réseaux neurologiques, d'une partie qui
LY_SII __ 111 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
s'exercent rapidement et d'une partie qui exigent beaucoup de passages au-dessus des données
avant qu'ils apprennent les tâches assignées. Des réseaux neurologiques peuvent être
employés dans dirigé, non surveillé, et le renfort apprenant des scénarios. Ils peuvent être
employés pour la classification, le groupement, et la prévision. Dans beaucoup d'applications,
les réseaux neurologiques peuvent remplacer les systèmes experts, particulièrement où les
données suffisantes sont disponibles pour la formation.
Une pas simplement autre technique d'algorithme ou de régression d'étude, les réseaux
neurologiques réellement représentent un nouveau et différent modèle de calcul à partir des
ordinateurs périodiques de von Neumann nous que toute connaît et aiment (et employer
journalier). Empruntant fortement à la métaphore du cerveau humain, les réseaux
neurologiques ont des centaines ou des milliers de processeurs simples (appelés les unités de
traitement, traitant des éléments, ou des neurones) reliés par des centaines ou des milliers de
poids adaptatifs comme illustré sur le schéma 5.1. Ce réseau des processeurs et des
raccordements forme un ordinateur parallèle qui peut de manière adaptative se refaire
l'installation électrique quand il est exposé aux données. Les poids adaptatifs sont ajustés et
forment la mémoire de l'ordinateur de réseau neurologique, jouant le rôle que la synapse a
dans le cerveau humain. Une autre différence entre les réseaux neurologiques et les
calculateurs numériques traditionnels est que les processeurs de réseau neurologique sont
analogue, non numérique. Ils ne crachent pas dehors 1s binaire et 0s, ils produisent une
gamme continue des sorties, habituellement de 0.0 à 1.0. Le nombre infini de valeurs réelles
entre 0 et 1 peut être employé à notre avantage.
Propagation arrière
La propagation arrière est l'architecture la plus populaire de réseau neurologique pour l'étude
dirigée. Elle comporte une topologie de raccordement de réaction, signifiant que les données
traversent le réseau dans une direction simple, et emploient une technique appelée la
propagation en arrière des erreurs pour ajuster les poids de raccordement (Rumelhart,
Hinton, et Williams 1986). En plus d'une couche d'unités d'entrée et de rendement, un réseau
de rétropropagation peut avoir une ou plusieurs couches d'unités cachées, qui reçoivent des
entrées seulement à partir d'autres unités, pas l'environnement externe. Un réseau de
rétropropagation avec une seule couche cachée d'unités de traitement peut apprendre à
modeler n'importe quelle fonction continue une fois donné assez d'unités dans la couche
cachée. Les applications primaires des réseaux de rétropropagation sont pour la prévision et la
classification.
Chaque unité d'entrée de réseau prend une valeur numérique simple, XI, qui est
habituellement mesurée ou normalisée à une valeur entre 0.0 et 1.0. Cette valeur devient
l'activation d'unité d'entrée. Après, nous devons propager les données en avant, par le réseau
neurologique. Pour chaque unité dans la couche cachée, nous calculons la somme des produits
des activation d'unité d'entrée et des poids reliant ceux les unités entrées de couche à la
couche cachée. Cette somme est le produit intérieur (également appelé le point ou le produit
scalaire) du vecteur d'entrée et des poids dans l'unité cachée. Une fois que cette somme est
calculée, nous ajoutons une valeur- seuil et puis passons cette somme par une fonction non
linéaire d'activation, f, produisant le yj d'activation d'unité suivant les indications du schéma
5.1. La formule pour calculer l'activation de n'importe quelle unité dans une couche cachée ou
de rendement dans le réseau est :
f(sumj) = 1 / 1 + e-sumj.
là où le wij est l'unité se reliante i de poids à l'unité j, le η est le paramètre de taux d'étude, le
δj est le signal d'erreur pour cette unité, et yi est le rendement ou la valeur d'activation de
l'unité i. Pour des unités dans la couche de rendement, le signal d'erreur est la différence entre
le tj de rendement de cible et le yj réel de rendement multipliés par le dérivé de la fonction
logistique d'activation.
LY_SII __ 113 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Pour chaque unité dans la couche cachée, le signal d'erreur est le dérivé de la fonction
d'activation multipliée par la somme des produits des poids sortants de raccordement et de
leurs signaux correspondants d'erreur. Ainsi pour l'unité cachée j
là où k s'étend au-dessus des index des unités recevant le signal de sortie de l'unité j.
Une modification commune de la règle de mise à jour de poids est l'utilisation d'une limite a
d'élan, de réduire l'oscillation des poids. Ainsi, le changement de poids devient une
combinaison du changement courant de poids, calculée comme avant, plus une certaine
fraction (le α s'étend de 0 à 1) du changement précédent de poids. Ceci complique l'exécution
parce que nous maintenant devons stocker les changements de poids de l'étape antérieure.
La base mathématique pour la propagation en arrière est décrite en détail dans Rumelhart,
Hinton, et Williams (1986). Quand les changements de poids se résument (ou sont traités en
lots) au-dessus d'une présentation entière de l'ensemble de formation, la fonction de
minimisation d'erreur remplie s'appelle la descente de gradient. Dans la pratique, la plupart
des personnes mettent à jour immédiatement les poids de réseau après que chaque vecteur
d'entrée soit présenté. Tandis que des mises à jour de modèle, en tant que ceci s'appelle, peut
parfois produire le comportement indésirable, il a habituellement comme conséquence une
formation plus rapide qu'using les mises à jour en lots.
Cartes de Kohonen
Les cartes à organisation autonome de dispositif se sont développées par Tuevo Kohonen ont
devenu des modèles les plus populaires et les plus pratiques de réseau neurologique (Kohonen
1990). Une carte de Kohonen est un réseau neurologique à une seule couche, consisté en une
couche d'entrée et une couche de rendement. À la différence de la propagation arrière, qui est
un paradigme de étude dirigé, les cartes de dispositif effectuent l'étude non surveillée. Chaque
fois que un vecteur d'entrée est présenté au réseau, sa distance à chaque unité dans la couche
de rendement est calculée. De diverses mesures de distance ont été employées. Plus le terrain
communal et celui utilisés ici est juste la distance euclidienne. L'unité de rendement avec la
plus petite distance au vecteur d'entrée est déclarée le « gagnant. » L'unité de gain et un
ensemble d'unités dans les poids de voisinage sont ajustés en déplaçant les poids vers le
vecteur d'entrée. Au commencement, le voisinage et le taux de étude sont tout à fait grands et
ainsi beaucoup d'unités sont déplacées autour l'espace d'entrée pour assortir l'ensemble de
vecteurs de formation. Pendant que la formation progresse, le voisinage se rétrécit et le taux
de étude est diminué. La carte de Kohonen individu-organise avec le temps, et à la fin d'une
course réussie de formation, une carte topographique est créée. Un attribut d'une telle carte est
que les entrées qui sont près de l'un l'autre dans la carte de l'espace d'entrée sur les unités de
rendement qui sont dans la grande proximité dans la couche de rendement du réseau
neurologique.
LY_SII __ 114 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Sur le schéma 5.4, nous montrons un schéma de principe d'une carte de Kohonen. D'abord les
entrées sont présentées à la couche d'entrée. En second lieu, la distance du modèle d'entrée
aux poids à chaque unité de rendement est calculée using la formule euclidienne de distance
ci-dessous :
yj= || x - wj || 2
là où I et j sont les coordonnées des unités dans la carte bidimensionnelle, et k est le nombre
d'itération. le σ (k) 2 est la largeur de la fonction de voisinage, qui commence aussi au loin que
la carte quand k est petit et diminue à une valeur finale entourant une unité simple quand k est
à sa valeur maximum. Le α (k) le paramètre est le taux d'étude pour l'itération K. Ceci est
calculé comme :
là où la limite de kmax est le nombre maximum des itérations à exécuter. Le α de taux d'étude
(k) exponentiellement les diminutions comme nombre k d'itération devient plus grande. Nous
commençons à l'itération k = 0 avec le αinitial apprenons le taux et finissons à l'itération k =
kmax avec la valeur de αfinal. Les valeurs typiques pour αinitial et le αfinal sont 1.0 et 0.05
respectivement. Ces formules sont employées comme base pour notre exécution de Java,
décrite plus tard en ce chapitre.
Arbres de décision
Les arbres de décision effectuent l'induction sur des ensembles de données d'exemple,
produisant des classificateurs et des modèles de prévision. Un arbre de décision examine
l'ensemble de données, et emploie la théorie de l'information pour déterminer quel attribut
contient la plupart d'information sur laquelle pour baser une décision. Cet attribut est alors
employé dans un noeud de décision pour couper l'ensemble de données en deux groupes,
basés sur la valeur de cet attribut. À chaque noeud suivant de décision, l'ensemble de données
est dédoublé encore. Le résultat est un arbre de décision, une collection de noeuds. Les
noeuds de feuille représentent une classification finale du disque. Les exemples des
algorithmes d'arbre de décision sont ID3 (Quinlan 1986) et les systèmes C4.5. Une limite
LY_SII __ 115 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
générique pour la classe des algorithmes d'arbre de décision est CHARIOT, pour des arbres
de classification et de régression.
Théorie de l'information
Des arbres de décision sont basés sur la théorie de l'information, un concept mathématique
d'abord présenté par Shannon et Weaver (1949). L'unité d'information est un peu, et la
quantité de l'information dans une réponse binaire simple est log2P (v), où P (v) est la
probabilité de l'événement v se produisant. Le contenu de l'information est basé sur les
probabilités antérieures d'obtenir la réponse correcte à une question ou à une classification
(Russell et Norvig 1995). Supposer que nous essayons de classifier les clients qui
remplaceront leurs comptes de service d'Internet ou les décommanderont et commuteront à un
concurrent. Assumons-nous a eu l'année dernière 1000 clients, 800 qui ont remplacé et 200
qui ont décommandé. Nous ferions placer une formation avec 1000 disques, contenant un
certain ensemble d'attributs de ces clients (leur âge, sexe, revenu, temps de connexion
mensuel de moyenne, années comme clients, etc.) aussi bien que l'information dessus s'ils ont
remplacé ou ont décommandé leur service. Ceux qui nous ont remplacés considèrent les
exemples positifs, P. Ceux qui nous ont décommandés considèrent les exemples négatifs, N.
Si nous avions l'information sur un client et devions essayer de prévoir si ce client
remplacerait ou décommanderait, combien d'information serait contenue dans une réponse
correcte ? La formule utilisée est
Noter que le dénominateur en tous les termes est tout le nombre de disques. La première
limite est la probabilité que le cas positif se produit (p/(p + n)) s'est multiplié par la teneur en
information de ce journal d'événement 2 (p/(p + n)). La deuxième limite est une expression
équivalente appliquée aux exemples négatifs. Dans notre exemple de service d'Internet, la
chance que n'importe quel facteur simple (par exemple, âge) diviserait complètement le
groupe en ceux qui remplacerait ou l'annulation est petite. Nous devons mesurer de combien
d'informations nous avons besoin toujours après l'essai. N'importe quel attribut A qui a des
valeurs distinctes de v divise l'ensemble de données en sous-ensembles de v selon les valeurs
de l'A. Chaque sous-ensemble en résultant des données de formation a son propre maquillage
des résultats de p et de n. En moyenne, après qu'examinant l'attribut A, nous avons besoin
toujours
Comme exemple, supposer que les hommes remplacent 90 pour cent du temps, et des femmes
remplacent 70 pour cent, et que notre ensemble de client est moitié composée des hommes et
moitié des femmes. Combien de gain de l'information obtiendrions-nous simplement par
l'essai si un client est masculin ou femelle ?
LY_SII __ 116 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Supposer que nous habitudes d'utilisation avions groupé clients des' dans 3 groupes : au-
dessous de 4 heures par mois, de 4 à 10 heures, et plus de 10. supposent également qu'elles
ont été également dédoublées entre tous les clients. Quand nous regardons leurs taux de
renouvellement, nous voyons que le premier groupe remplace à 50 pour cent, à la seconde à
90 pour cent, et au tiers à 100 pour cent. Quelle information obtiendrions-nous par l'essai sur
cet attribut ?
Vous pouvez voir que dans cet exemple, le deuxième cas nous donne plus de gain de
l'information que le premier. Ainsi, si nous construisions un arbre de décision, nous voudrions
à la première fente que les données ont basée sur combien de temps de connexion elles ont
employé, et puis dessus si le client était masculin ou femelle. Ce processus de dédoubler les
données, basé sur les paires d'attribuer-valeur contenant la plupart d'information, est continué
jusqu'à ce que nous puissions classifier les données à notre degré d'exactitude désiré.
Apprendre l'applet
Dans cette section nous décrivons un applet qui démontre trois techniques d'étude. Celles-ci
incluent deux types des réseaux neurologiques et d'un classificateur d'arbre. Avant que nous
entrions dans les détails des réalisations des algorithmes d'étude, nous devons présenter
quelques classes d'aide. Le schéma 5.5 montre la disposition de notre applet de étude. Il
comporte deux zones d'exposition des textes, une pour les données employées pour former les
réseaux neurologiques ou le classificateur d'arbre, et une pour l'information de trace des
modèles elles-mêmes.
Avant que nous entrions dans les détails de l'exécution de l'applet d'étude, nous devons
présenter deux sous-classes de la classe variable pour l'usage dans les algorithmes d'étude.
Ces classes traitent spécifiquement des variables discrètes et continues et soutiennent le
comportement exigé pour la normalisation de données exigée par les algorithmes de réseau
neurologique.
Variables continues
variable comme seul paramètre. La minute et les membres maximum peuvent être placés
suivre le setMin () et des méthodes de setMax () directement, ou elles peuvent être calculées
automatiquement si le ContinuousVariable est employé en tant qu'élément d'un ensemble de
données en appelant la méthode de computeStatistics (). La méthode de normalisation () est
employée par la classe d'ensemble de données quand elle crée une version tout-numérique
d'un ensemble de données. Cette méthode fait une graduation linéaire simple de la valeur
d'entrée à une valeur dans la gamme de 0.0 à 1.0. La classe de ContinuousVariable hérite de
la méthode de normalizedSize () de la classe variable, parce que la taille normale est toujours
1.
};
Variables discrètes
La classe de DiscreteVariable est une sous-classe de variable. Elle fournit l'appui nécessaire
pour les variables qui peuvent prendre un ensemble prédéfini de valeurs numériques ou
symboliques. Le constructeur prend le nom de la variable comme seul paramètre. Le
minimum et les valeurs maximum peuvent être placés suivre le setMin () et des méthodes de
setMax () directement, ou ils peuvent être calculés automatiquement si le DiscreteVariable
est employé en tant qu'élément d'un ensemble de données en appelant la méthode de
computeStatistics (). On assume que la valeur est symbolique. Si le symbole est déjà dans les
étiquettes puis il est ignoré ; autrement, on l'ajoute à la liste. La méthode de normalisation ()
est employée par la classe d'ensemble de données quand elle crée une version tout-
numérique d'un ensemble de données. Cette méthode convertit chaque symbole en sa valeur et
LY_SII __ 118 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
puis convertis d'index qui dans un-de-n code. La méthode de normalizedSize () renvoie le
nombre de valeurs discrètes uniques que la variable peut prendre, qui est également la taille
d'un-de-n code quand la variable est normale. La méthode de getDecodedValue () est
employée pour transformer le rendement d'un réseau neurologique de nouveau dans une
valeur de corde pour l'affichage.
Integer min ;
Integer max ;
};
Nous fournissons aux ensembles de données multiples pour l'usage les trois techniques
d'étude. Celles-ci incluent exclusif-OU l'ensemble de données, un ensemble de données de
LY_SII __ 119 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
véhicules qui reflète la base de règle de véhicules utilisée dans le chapitre 4, un ensemble de
données de restaurant, un ensemble de données linéaire de rampe, et un ensemble de données
de groupement. Chaque ensemble de données est employé pour préciser des aspects
spécifiques de nos algorithmes d'étude. Puisque chacun des trois algorithmes se sert d'un
ensemble de données de formation, nous avons conçu et avons mis en application une classe
de Java de terrain communal DataSet appelé. La définition de classe d'ensemble de données
est montrée ci-dessous. Elle se sert du paquet de java.io pour charger les données à partir des
dossiers plats des textes dans la mémoire, et emploie également les classes de java.awt
(TextArea) pour montrer les données et pour l'information de trace. Chaque exemple
d'ensemble de données a un nom, un membre pour stocker le nom de fichier, et un drapeau
booléen qui indique s'il y a des données symboliques dans le dossier. Deux vecteurs sont
employés pour stocker les données lus du dossier et d'un ensemble de données normal, que
nous discuterons plus tard. La table de brouillage de variableList tient un ensemble de
variables qui définissent les types de données logiques pour chaque champ dans le dossier.
Le membre de fieldList tient des références aux mêmes variables que le variableList, mais les
variables sont ajoutées au vecteur dans l'ordre qu'elles sont ajoutées à l'ensemble de
données, suivant les indications de la méthode addVariable. Ceci nous permet d'avoir une
correspondance linéaire entre les champs dans le dossier et les variables qui définissent les
données. Le membre de fieldsPerRec est équivalent à la taille du fieldList et est donné pour la
convenance. NumRecords est placé au nombre de disques dans le dossier.
int fieldsPerRec=0;
int normFieldsPerRec=0;
int numRecords=0 ;
. . .
Nous incluons une charge statique TextArea qui est employée par l'applet pour montrer des
informations sur l'ensemble de données. La méthode de trace écrit simplement une corde au
TextArea.
Une des méthodes principales dans la classe d'ensemble de données est () la méthode
loadDataFile. Cette méthode ne prend aucun paramètre parce que toutes les informations
nécessaires pour lire le dossier dans la mémoire sont fournies sur le constructeur d'ensemble
de données (). Avant que nous chargions le fichier de données, nous avons lu la première fois
la définition de format de fichier suivre la méthode de loadDataFileDefinition (). Nous
employons un FileInputStream pour lire des données à partir du dossier. Nous employons la
méthode de readLine () pour lire une ligne à la fois et un StringTokenizer pour analyser
dehors chaque valeur de champ. Selon, que le dossier contienne toutes les données
numériques ou pas, nous instancions une nouvelle corde ou flottons la rangée pour détenir le
record. Cette rangée est alors ajoutée au vecteur de données. Car nous lisons le dossier, nous
maintenons la taille du dossier et stockons cette information dans le membre de numRecords.
String line=null ;
trace(“\nReading file ” + fileName + “.dat with ” +
fieldsPerRec + “ fields per record\n ”) ;
LY_SII __ 121 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
DataInputStream in=null ;
try {
in = new DataInputStream(new FileInputStream(fileName + “.dat”));
} catch (FileNotFoundException exc) {
trace(“Error: Can't find file ” + fileName + “.dat” ) ;
}
int recInx = 0 ;
int token= 0 ;
StringTokenizer input = null ;
do {
try {
line = in.readLine();
if (line != null) {
input = new StringTokenizer(line) ;
tempRec = new String[fieldsPerRec] ;
data.addElement(tempRec) ; // add record
} else {
break ;
}
} catch (IOException exc){
trace(“Error reading file: ” + fileName + “.dat”) ;
}
La définition de fichier de données est un dossier simple des textes qui contient une liste des
types de données de champ et de leurs noms. Un champ simple doit être indiqué comme
« ClassField. » Les types de données peuvent être ou « continus, » « discret, » ou
« catégorique. » Dans l'exécution courante, discret et catégorique sont traités les mêmes.
Pendant que chaque type de champ est lu à partir du dossier de définition de données, une
variable de ce type est instanciée avec le nom spécifique, et la variable est alors ajoutée à
l'ensemble de données suivre () la méthode addVariable. On assume que les champs sont
définis dans le même ordre comme les données correspondantes dans le fichier de données.
String line=null ;
trace(“\nReading file definition ” + fileName + “.dfn with ” +
fieldsPerRec + “ fields per record\n ”) ;
DataInputStream in=null ;
try {
in = new DataInputStream(new FileInputStream(fileName + “.dfn”));
LY_SII __ 122 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
int recInx = 0 ;
int token= 0 ;
StringTokenizer input = null ;
do {
try {
line = in.readLine();
if (line != null) {
input = new StringTokenizer(line) ;
} else {
break ;
}
} catch (IOException exc){
trace(“Error reading file: ” + fileName + “.dfn”) ;
}
Les membres suivants font partie de la classe variable présentée dans le chapitre précédent, et
sont employés par la classe d'ensemble de données.
Les trois prochaines méthodes traitent des données normales. Les réseaux neurologiques
exigent toutes les données d'entrée numériques et tellement n'importe quels ensembles de
données qui contiennent des symboles doivent être prétraités. En outre, les réseaux
neurologiques exigent habituellement les données d'entrée soient mesurés à une gamme
spécifique, dans notre cas, de 0.0 à 1.0. Cette conversion des données et de la graduation
symboliques des données continues s'appelle la normalisation. Nous employons les
définitions variables pour déterminer comment normaliser les données. Quand nous avons un
DiscreteVariable, nous prenons le symbole ou le nombre et obtenons sa valeur d'index. Cette
valeur d'index est alors convertie en un-de-n vector. Par exemple, si nous avons {oui, non,
peut-être} en tant que trois cordes possibles dans un domaine défini comme
DiscreteVariable, nous convertirions chaque symbole en code de 1s et de 0s dont la longueur
est égale au nombre de valeurs discrètes. Tellement « oui » ne tracerait à 1 0 0, « non » à 0 1
0, et « peut-être » à 0 0 1. Noter également que nous avons une expansion ici. Un disque
d'entrée avec 10 champs de DiscreteVariable, chacun ayant trois valeurs possibles,
augmenterait dans une rangée de trente-élément pour la présentation au réseau neurologique.
Une autre conversion que nous devons faire est de mesurer les données continues qui sont
hors de la gamme 0.0 à 1.0. Nous faisons une graduation linéaire simple ici. Il y a des
techniques plus sophistiquées qui pourraient être employées. L'utilité de réseau neurologique
d'IBM, par exemple, emploie une technique bilinéaire de graduation où le point médian de la
plage des données d'entrée est tracé au point médian (0.5) de la plage des données de
rendement. Ceci tend « à se concentrer » les données sur 0.5 dans les cas où il y a des annexes
ou d'autres anomalies. Noter que notre un-de-n scaling utilisée pour des données discrètes est
déjà dans les 0 à 1 gammes, ainsi aucune graduation additionnelle est nécessaire.
int sum = 0 ;
Enumeration vars = variableList.elements() ;
while (vars.hasMoreElements()) {
Variable thisVar = (Variable)vars.nextElement() ;
sum += thisVar.normalizedSize() ;
}
return sum ;
}
}
normalizedData.addElement(normNumRec) ;
}
}
float tempNumRec[] ;
Les méthodes de getClassFieldValue () sont employées pour montrer les résultats après
qu'une course de formation de réseau neurologique. La première méthode prend l'index record
et renvoie la valeur originale de « ClassField ». La deuxième méthode prend une rangée de
flotteurs et l'index commençant de l'unité de rendement. La méthode de
DiscreteVariable.getDecodedValue () est employée pour choisir l'élément de tableau avec la
valeur maximum, la convertit en index variable discret, et puis recherche la valeur de corde
correspondante. C'est essentiellement l'inverse des étapes exécutées dans le normalizeData ()
quand une valeur discrète est transformée en un-de-n code.
Dans les sections suivantes, nous présentons nos réalisations de Java des modèles arrières de
réseau neurologique de propagation et de carte de Kohonen. Ils sont orientés objectivement,
mais pas servile ainsi. Nous voudrions que ces algorithmes fonctionnent en nombre de heures
raisonnable sur le matériel de PC standard. Ainsi nous n'avons pas des objets pour chaque
unité ou couche de traitement. Notre expérience prouve que nous pouvons avoir les avantages
de la conception orientée objectivement et l'exécution du code algorithmique optimisé.
Dans cette section, nous décrivons notre exécution de la propagation arrière. La classe de
BackProp a quatre ensembles différents de membres ou de paramètres de données. Est
d'abord un ensemble qui est employé pour contrôler les données. Nous avons une référence à
un objet d'ensemble de données, au ds, à l'index d'article courant, au recInx, à tout le nombre
de disques dans l'ensemble de données, aux numRecs, et à nombre de champs par disque,
fieldsPerRec. Est après un ensemble de paramètres d'architecture de réseau. Ceux-ci incluent
les numInputs, numHid1, et les numOutputs, qui définissent le nombre d'unités dans chacune
des trois couches réseau. Quelques réalisations soutiennent des couches cachées multiples.
Cette conception peut être facilement prolongée pour fournir cet appui. NumUnits est la
somme des trois couches d'unités, et les numWeights est tout le nombre de poids dans le
réseau.
Dans notre exécution, nous fournissons les paramètres de commande suivants : mode,
learnRate, élan, et tolérance. Quand le paramètre de mode est placé à une valeur de 0, le
réseau est en mode de formation et les poids de raccordement sont ajustés. Quand le mode est
placé à 1, les poids de réseau sont verrouillés. Les paramètres de learnRate et d'élan sont
employés pour commander la taille des mises à jour de poids comme décrit plus tôt. Le
paramètre de tolérance est employé pour spécifier combien étroit la valeur prévue de
rendement doit être à la valeur désirée de rendement avant que l'erreur soit considérée 0. Par
exemple, si notre valeur désirée de rendement était 1.0, avec une tolérance de 0.1, n'importe
quelle valeur prévue de rendement plus considérablement que 0.9 aurait comme conséquence
0 erreurs.
Après, nous avons un ensemble de rangées de données et d'erreurs. Les rangées primaires sont
les activation, les poids, et les seuils. Celles-ci spécifient l'état actuel du réseau. La rangée
d'enseignement tient les valeurs désiré ou de cible de rendement. Les autres rangées sont
employées dans le calcul des changements d'erreur et de poids.
// data parameters
static DataSet ds ;
Vector data ; // train/test data from file
int recInx=0 ; // current record index
int numRecs=0 ; // number of records in data
int fieldsPerRec=0;
// error measures
float sumSquaredError ; // total SSE for an epoch
LY_SII __ 126 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
// network data
float activations[] ;
float weights[] ;
float wDerivs[] ;
float thresholds[];
float tDerivs[] ;
float tDeltas[] ;
float teach[]; // target output values
float error[];
float deltas[]; // the error deltas
float wDeltas[] ;
TextArea textArea1 ;
BackProp(String Name) {
name = Name ;
data = new Vector() ;
}
}
LY_SII __ 127 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
return;
}
Pour le passage vers l'avant, trois méthodes sont employées. La méthode de readInputs ()
prend un disque de l'ensemble de données et copie les valeurs d'entrée dans les activation des
unités d'entrée. Elle copie également les valeurs à atteindre dans la rangée d'enseignement. La
méthode de computeOutputs () fait le passage vers l'avant complet par le réseau. Commençant
par la première couche, elle calcule la somme du seuil et de chaque activation d'unité d'entrée
multipliés par le poids correspondant, et puis appelle () la méthode logistique pour calculer et
placer la valeur d'activation.
// first layer
int inx = 0 ;
for(i = firstHid1 ; i < firstOut ; i++) {
float sum = thresholds[i];
for (j = 0 ; j < numInputs ; j++) { // compute net inputs
sum += activations[j] * weights[inx++] ;
}
activations[i] = logistic(sum) ; // compute activation
}
// second layer
for(i = firstOut ; i < numUnits ; i++) {
float sum = thresholds[i] ;
for (j = firstHid1 ; j < firstOut ; j++) { // compute sum
sum += activations[j] * weights[inx++] ;
}
activations[i] = logistic(sum) ; // compute activation
}
}
Pour calculer les erreurs, nous commençons à la couche de rendement et travaillons en arrière
vers l'entrée. D'abord, les erreurs de rendement sont calculées en prenant la différence entre
les activation produites par des computeOutputs () et les valeurs d'enseignement. Noter que
nous additionnons également les erreurs carrées ici pour calculer l'erreur moyenne de RMS.
Les deltas sont alors calculés using le dérivé de la fonction d'activation.
LY_SII __ 129 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Pour ajuster les poids, la méthode d'adjustWeights () calcule d'abord les deltas courants de
poids, wDeltas, et ajoute ensuite ces deltas aux poids. Noter que nous employons la rangée de
wDerivs, qui tient l'ensemble accumulé de modifications de poids qui devraient être apportées
aux poids. Dans la mise à jour de modèle, les wDerivs tient seulement les changements du
modèle courant. Cependant, si nous voulions employer le groupe mettant à jour, cette rangée
tiendrait les changements de tous les modèles de l'ensemble de données. Après que nous
LY_SII __ 130 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
ajustions les poids, nous mettons dehors la rangée de wDerivs. Après nous ajustons les poids
de seuil à chaque unité dans cachée et produisons la couche. Les calculs sont semblables à
ceux pour les poids réguliers. Note : Il n'est pas nécessaire d'avoir une rangée séparée de seuil.
Quelques réalisations juste ajoutent les poids additionnels aux rangées de poids et ajoutent
une unité additionnelle simple qui a une valeur constante d'activation de 1 à chaque couche.
}Pour voir comment notre réseau arrière de propagation fonctionne, nous pouvons employer
le notre apprenons l'applet. Using un navigateur Java-permis, s'ouvrir sur le dossier de
LearnApplet.html. Le dialogue d'applet d'étude suivant les indications du schéma 5.5 apparaît.
Choisir en arrière l'appui vertical comme méthode de étude et l'ensemble de données de
XOR dans la commande bien choisie au dessus du panneau. Cliquer dessus le bouton de
charge pour lire dedans les données de XOR. Le dossier de xor.dfn et les données seront
chargés dans l'ensemble de données et montrés dans la commande supérieure de TextArea.
Presser le bouton marche pour former le réseau arrière de propagation. Quand la formation
est complète, les valeurs désirées et réelles, le contenu de la rangée d'activation, et l'erreur
finale de la moyenne RMS seront montrés dans le TextArea inférieur.
Vous pouvez choisir d'autres ensembles de données pour travailler avec l'appui vertical
arrière, y compris les véhicules et les animaux pour la classification, et la rampe linéaire pour
LY_SII __ 131 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
voir un exemple d'un problème de prévision. Le contenu de chaque ensemble de données est
énuméré dans l'annexe B. Toutes les fois que vous choisissez un ensemble de données
différent, soit sûr d'appuyer sur le bouton de charge. Le bouton de remise dégagera le
TextArea inférieur et remettra à zéro les poids dans le réseau arrière d'appui vertical.
Pour notre exécution du réseau neurologique de carte de Kohonen, nous définissons une
classe appelée KMapNet. La structure de cette classe est semblable à celle de la classe de
BackProp déjà présentée en ce chapitre. La différence principale entre le KMapNet et la
classe de BackProp est la non surveillée contre le paradigme de étude dirigé. La carte de
Kohonen effectue l'étude non surveillée, tellement là n'est aucune notion d'un résultat désiré ;
il y a seulement des entrées.
Après nous avons un ensemble de rangées de données et d'erreurs. Les rangées primaires sont
les activation et les poids, qui spécifient l'état actuel du réseau. La rangée de distance est une
grille precomputed qui définit les distances entre les unités sur la grille bidimensionnelle de
rendement. Par exemple, dans un réseau avec un résultat 4 by-4, les distances à partir de
l'unité 0.0 (gauche supérieur) seraient :
0 1 16 81
1 2 17 82
16 17 32 97
81 82 97 162
Comme vous pouvez voir, la distance à partir de l'unité à elle-même est 0, à ces unités
horizontalement et verticalement adjacent elle est 1, et les distances se développent pendant
que vous vous éloignez de l'unité. La rangée de distance est employée dans la méthode
d'adjustNeighborhood ().
// data parameters
static DataSet ds;
Vector data ;
int recInx=0 ; // current record index
int numRecs=0 ; // number of records in data
int fieldsPerRec;
int numPasses=0 ;
// network data
int winner ; // index of the winning unit
float activations[];
float weights[];
int distance[]; // used in neighborhood computation
KMapNet(String Name) {
name = Name ;
data = new Vector() ;
}
}
public void display_network() {
// show_array(“weights”,weights);
show_array(“activations”,activations) ;
textArea1.appendText(“\nWinner = ” + winner + “\n”) ;
}
. .
// create arrays
activations = new float[numUnits];
weights = new float[numInputs*numOutputs];
Pour traiter un modèle d'entrée, trois méthodes sont employées. La méthode de ReadInputs ()
prend un disque de l'ensemble de données et copie les valeurs d'entrée dans les activation des
unités de couche d'entrée. Puisque les cartes de Kohonen emploient l'étude non surveillée, il
n'y a aucune valeur à atteindre. La méthode de computeOutputs () calcule la distance
euclidienne entre le vecteur d'entrée et les vecteurs de poids. La méthode de computeWinner
() choisit le rendement avec l'activation minimum (le plus étroitement au vecteur d'entrée) en
tant que gagnant. Note, nous pourrions faire cette fonction dans notre méthode de
computeOutputs () dans ce cas-ci. Cependant, si nous ajoutons des techniques plus
sophistiquées de choix de gagnant, telles que l'étude avec une conscience, nous voudrions ceci
éclaté dans une étape séparée.
//first layer
for(i = firstOut ; i <= lastOut ; i++) {
index = (i - firstOut) * numInputs;
activations[i] = (float)0.0 ;
for (j = 0 ; j < numInputs ; j++) { // compute net inputs
activations[i] += (activations[j] - weights[index+j]) *
(activations[j] - weights[index+j]);
}
}
}
winner = 0;
float min = activations[numInputs];
Une fois que le gagnant est choisi, les poids sont ajustés. Dans les adjustWeights () méthode,
nous employons le voisinage, la distance à partir de l'unité de gain, et le learnRate pour
ajuster les poids d'unités dans le voisinage du gagnant.
Maintenant, tournons-nous vers notre exécution d'un algorithme d'arbre de décision qui
manipule des variables discrètes. Il y a deux classes principales : un noeud qui représente un
noeud d'arbre de décision, et la classe de DecisionTree elle-même. Le noeud a un nom ou
étiquette, un vecteur des liens à d'autres noeuds dans le DecisionTree, une référence au
noeud de parent, et un vecteur contenant des références aux noeuds d'enfants.
DecisionTree.appendText(“\nLink - ” +
(String)enum2.nextElement()) ;
displayTree((Node)enum.nextElement()) ;
}
}
}
};
DecisionTree(String Name) {
name = Name;
}
. . .
}
La méthode de buildDecisionTree () est la méthode principale dans cette classe. Elle prend
trois paramètres, un vecteur des exemples (l'ensemble de données), une liste des définitions
de champ, et la valeur par défaut qui devrait être retournée au cas où l'arbre de décision
échouerait. La première chose que nous faisons est instancient un noeud de racine pour
l'arbre de décision. Si l'ensemble de formation est vide, alors nous retournons avec la valeur
par défaut. Autrement, si tous les disques dans l'ensemble de formation ont une valeur
identique pour le champ de classe, nous retournons avec un noeud de feuille avec cette
valeur. Si ni l'un ni l'autre de ces deux conditions ne sont vraies, nous devons construire un
arbre de décision. La première étape est de choisir le meilleur attribut ou variable sur lesquels
pour se dédoubler. () La méthode chooseVariable fait ce choix using la théorie de
l'information. Nous assignons la racine de cet arbre à un noeud pour cette variable.
Maintenant que nous avons décidé quelle variable à dédoubler dessus, nous devons
déterminer quelle valeur discrète de cet attribut nous devrions employer pour la fente. Pour ()
la boucle fait ceci en prenant chaque valeur possible du variable, subsetting les données de
formation (exemples) dans des groupes où tous les disques ont la valeur désirée de cet
attribut, et calculant le gain de l'information pour cette valeur de la variable. Nous appelons
LY_SII __ 138 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
while(enum.hasMoreElements()) {
Variable tempVar = (Variable)enum.nextElement() ;
LY_SII __ 139 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
double total = p + n ;
double pos = p / total ;
double neg = n / total;
double temp;
if ((p ==0) || (n == 0)) {
temp = 0.0 ;
} else {
temp = (-1.0 * (pos * Math.log(pos)/Math.log(2))) -
(neg * Math.log(neg)/Math.log(2)) ;
}
return temp ;
}
negative[i]++;
}
}
} /* endwhile */
double weight = (positive[i]+negative[i]) / numRecs;
double myrem = weight * computeInfo(positive[i], negative[i]);
sum = sum + myrem ;
} /* endfor */
return sum ;
}
while(enum.hasMoreElements()) {
String[] record = (String[])enum.nextElement() ;
if (value.equals(record[index])) {
matchingExamples.addElement(record) ;
}
}
textArea1.appendText(“\n Subset - there are ” +
matchingExamples.size() +
“ records with ” +
variable.name + “ = ” + value) ;
return matchingExamples;
}
}
LY_SII __ 141 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
while(enum.hasMoreElements()) {
String value = ((String[])enum.nextElement())[index];
int inx = ((Variable)classVar).getIndex(value) ;
counts[inx]++;
} /* enbwhile */
int maxVal = 0 ;
int maxIndex = 0 ;
for(int i=0 ; i < classVar.labels.size() ; i++) {
if (counts[i] > maxVal) {
maxVal = counts[i] ;
maxIndex = i ;
} /* endif */
} /* endfor */
return classVar.getLabel(maxIndex);
}
while(enum.hasMoreElements()) {
String value = ((String[])enum.nextElement())[index];
int inx = ((Variable)classVar).getIndex(value);
counts[inx]++;
} /* enbwhile */
return counts;
}
Nous employons l'ensemble de données de restaurant et notre apprendre l'applet pour montrer
un exemple d'un arbre de décision. Using un navigateur Java-permis, ouvrir le dossier de
LearnApplet.html. Le dialogue d'applet d'étude suivant les indications du schéma 5.5 apparaît.
Choisir l'arbre de décision comme méthode de étude et l'ensemble de données de restaurant
dans la commande bien choisie au dessus du panneau. Cliquer dessus le bouton de charge
pour lire dedans les données de restaurant. Le dossier de resttree.dfn et les données seront
chargés dans l'ensemble de données et montrés dans la commande supérieure de TextArea.
Presser le bouton marche pour construire l'arbre de décision. Quand la formation est
complète, la structure de l'arbre de décision sera montrée dans le TextArea inférieur.
L'applet d'étude est un Java applet Qui a été développé using l'instrument de développement
visuel de Symantec CafŽ. La vue d'applet se compose de deux commandes de TextArea
pour montrer l'ensemble de données et former l'information respectivement, de trois
commandes de radiobutton pour choisir l'algorithme d'étude, d'une commande bien choisie
LY_SII __ 142 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
if (radioButton1.getState() == true)
testBackProp(dataSet, textArea2);
if (radioButton2.getState() == true)
testKMapNet(dataSet,textArea2) ;
if (radioButton3.getState() == true)
testDecisionTree(dataSet, textArea2);
}
// stop
void button2_Clicked(Event event) {
// for future use
}
// reset
void button3_Clicked(Event event) {
//{{CONNECTION
// Clear the text for TextArea
textArea2.setText(“”);
//}}
}
//{{INIT_CONTROLS
setLayout(null);
addNotify();
resize(518,495);
label1 = new java.awt.Label(“Data Set”);
label1.reshape(12,12,168,25);
add(label1);
textArea1 = new java.awt.TextArea();
textArea1.reshape(0,48,516,120);
add(textArea1);
textArea2 = new java.awt.TextArea();
textArea2.reshape(0,204,516,168);
LY_SII __ 143 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
add(textArea2);
button1 = new java.awt.Button(“Start”);
button1.reshape(36,444,96,36);
add(button1);
button2 = new java.awt.Button(“Stop”);
button2.reshape(192,444,109,32);
add(button2);
button3 = new java.awt.Button(“Reset”);
button3.reshape(372,444,97,36);
add(button3);
radioButtonGroupPanel1 =
new symantec.itools.awt.RadioButtonGroupPanel();
radioButtonGroupPanel1.setLayout(null);
radioButtonGroupPanel1.reshape(12,384,499,43);
add(radioButtonGroupPanel1);
Group1 = new CheckboxGroup();
radioButton1 = new java.awt.Checkbox(“back prop”,
Group1, false);
radioButton1.reshape(24,12,135,24);
radioButtonGroupPanel1.add(radioButton1);
radioButton2 = new java.awt.Checkbox(“Kohonen map”,
Group1, false);
radioButton2.reshape(180,12,114,22);
radioButtonGroupPanel1.add(radioButton2);
radioButton3 = new java.awt.Checkbox(“Decision Tree”,
Group1, false);
radioButton3.reshape(348,12,132,24);
radioButtonGroupPanel1.add(radioButton3);
choice1 = new java.awt.Choice();
add(choice1);
choice1.reshape(180,12,182,24);
label2 = new java.awt.Label(“Status ”);
label2.reshape(0,168,416,31);
add(label2);
button4 = new java.awt.Button(“Load”);
button4.reshape(396,12,108,28);
add(button4);
//}}
radioButton1.setState(true) ; // select back prop
DataSet.setDisplay(textArea1) ; // top text area
dataSets = new Hashtable() ;
choice1.addItem(“XOR”) ; // select XOR as default
dataSets.put(“XOR”, new DataSet(“XOR”,“xor”)) ;
choice1.addItem(“Vehicles”);
dataSets.put(“Vehicles”,
new DataSet(“Vechicles”, “vehicles”)) ;
choice1.addItem(“Restaurant”);
dataSets.put(“Restaurant”,
new DataSet(“Restaurant”,“resttree”)) ;
choice1.addItem(“Linear Ramp”) ;
dataSets.put(“Linear Ramp”,
new DataSet(“Linear Ramp”,“ramp2”)) ;
choice1.addItem(“Cluster Data”) ;
dataSets.put(“Cluster Data”,
new DataSet(“Cluster Data”,“kmap1”)) ;
choice1.addItem(“Animal Data”) ;
dataSets.put(“Animal Data”,
new DataSet(“Animal Data”,“animal”)) ;
choice1.addItem(“XOR Tree Data”) ;
dataSets.put(“XOR Tree Data”,
LY_SII __ 144 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
//{{DECLARE_CONTROLS
java.awt.Label label1;
java.awt.TextArea textArea1;
java.awt.TextArea textArea2;
java.awt.Button button1;
java.awt.Button button2;
java.awt.Button button3;
symantec.itools.awt.RadioButtonGroupPanel radioButtonGroupPanel1;
java.awt.Checkbox radioButton1;
CheckboxGroup Group1;
java.awt.Checkbox radioButton2;
java.awt.Checkbox radioButton3;
java.awt.Choice choice1;
java.awt.Label label2;
java.awt.Button button4;
//}}
Hashtable dataSets ;
DataSet dataSet = null ;
testNet.createNetwork(numInputs,numInputs,numOutputs) ;
int maxNumPasses = 2500 ; // default -- could be on applet
int numSteps = maxNumPasses * testNet.numRecs ;
for (int i=0 ; i < numSteps; i++) {
testNet.process() ; // train
}
testNet.process() ; // test
testNet.display_network() ;
}
}
testNet.textArea1 = bottomText ;
testNet.ds = dataSet ;
testNet.numRecs = dataSet.numRecords ;
testNet.fieldsPerRec = dataSet.fieldsPerRec ;
testNet.data = dataSet.normalizedData ; // get vector of data
tree.textArea1.appendText(“Starting DecisionTree ”) ;
tree.fieldsPerRec = dataSet.fieldsPerRec;
tree.examples = dataSet.data ; // get vector of data
tree.variableList = dataSet.variableList ;
tree.classVar = (Variable)tree.variableList.get(“ClassField”) ;
tree.variableList.remove(“ClassField”) ;
}
LY_SII __ 146 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Systèmes de classificateur
Des systèmes de classificateur ont été développés par John Hollande comme manière de
présenter l'étude aux systèmes basés sur les règles. Son mécanisme a été basé sur une
technique connue sous le nom d'algorithmes génétiques.
Algorithmes génétiques
Les algorithmes génétiques utilisent une métaphore de processus biologique pour dériver des
solutions aux problèmes. D'abord, l'état de problème doit être codé dans une corde qui est
habituellement une corde binaire, mais pourrait être une corde des valeurs réelles. Il doit y a
une évaluation ou une fonction objective qui prend que corde codée comme entrée et produit
« qualité » ou des points biologiques de « forme physique ». Ces points sont alors employés
pour ranger un ensemble de cordes (individus dans la population des cordes) basées sur leur
forme physique. Si vous êtes familiarisé avec un quelconque des théories de Darwin vous
pouvez voir probablement où ceci va.
Les cordes (individus) qui sont les plus adaptées sont aléatoirement choisies survivre et
procréer même dans la prochaine génération des cordes. Deux opérateurs génétiquement
inspirés sont habitués pour modifier la corde choisie, afin d'essayer d'améliorer sa forme
physique et obtenir même plus près du but ou de la solution optima. D'abord, il y a la
mutation, qui, comme la mutation biologique, exécute des mutations aléatoires ou change
dans le chromosome de l'individu. Dans la caisse binaire habituelle de corde, nous renversons
aléatoirement quelque peu. En second lieu, il y a croisement, où deux en particulier individus
adaptés sont choisis et le matériel génétique de eux est combiné, formant un nouvel individu
ou enfant. Le raisonnement intuitif pour cette opération est que parce que les deux parents
étaient les individus convenables, il est probable bons que la progéniture également bien-soit
dotée en termes de fournir une bonne solution au problème actuel.
Des algorithmes génétiques sont en particulier adaptés aux problèmes d'optimisation parce
qu'ils, essentiellement, exécutent une recherche parallèle dans l'espace d'état. L'opérateur de
croisement injecte des grands nombres de bruit dans le processus pour s'assurer que l'espace
de recherche entier est couvert. L'opérateur de mutation permet fine-tuning des individus
d'ajustement en quelque sorte semblables aux techniques de colline-montée de recherche. Des
paramètres de commande sont employés pour déterminer combien grand la population est,
comment des individus sont choisis parmi la population, et combien de fois n'importe quels
mutation et croisement est exécutée.
Résumé
LY_SII __ 147 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
En ce chapitre, nous avons discuté des techniques d'étude de machine telles que les réseaux
neurologiques et les arbres de décision. Les questions principales incluent :
• Il y a plusieurs différentes formes d'étude. L'étude par coeur est basée sur la mémorisation
des exemples. L'extraction et l'induction de dispositif sont employées pour trouver des
caractéristiques importantes d'un problème et pour établir un modèle qui peut être employé
pour la prévision dans de nouvelles situations. Le groupement est une manière d'organiser
les modèles semblables en groupes.
• L'étude dirigée se fonde sur un professeur qui fournit les données d'entrée aussi bien que
la solution désirée. L'étude non surveillée dépend des données d'entrée seulement et ne fait
aucune demande sur connaître la solution. L'étude de renfort est un genre d'étude dirigée,
où la rétroaction est plus générale.
• En ligne l'étude signifie que l'agent s'adapte tandis que cela fonctionne. L'étude en différé
implique des données d'économie tandis que l'agent est travaillant et employant ces
données plus tard pour former l'agent.
• Les réseaux neurologiques sont des modèles d'informatique parallèle qui s'adaptent une
fois présentés avec des données de formation. Ils fonctionnent en modes dirigée, non
surveillés, et de renfort d'étude. Un réseau neurologique est composé d'un ensemble
d'unités de traitement simples et d'un ensemble de poids adaptatifs et à valeurs réelles de
raccordement. L'étude dans les réseaux neurologiques fait par l'ajustement des poids de
raccordement.
• Des réseaux arrières de propagation sont dirigés, les réseaux neurologiques de réaction qui
emploient la propagation en arrière de l'algorithme d'erreurs pour ajuster les poids de
raccordement. Ils sont employés pour des problèmes de classification et de prévision.
• Les réseaux de carte de Kohonen sont non surveillés, les réseaux neurologiques de réaction
qui individu-organisent et apprennent à tracer les entrées semblables sur les unités de
rendement qui sont dans la grande proximité entre eux. Les entrées sont mesurées using la
distance euclidienne dans un espace haut-dimensionnel d'entrée et sont tracées sur un
espace bidimensionnel de rendement. Les cartes de Kohonen exécutent le groupement des
données d'entrée.
• Les systèmes de classificateur sont des systèmes de règle qui emploient des algorithmes
génétiques pour modifier la base de règle. Les algorithmes génétiques utilisent une
métaphore biologique pour exécuter la recherche parallèle dans l'espace d'état. L'état de
problème est codé en tant que cordes binaires et est modifié using les opérateurs génétiques
tels que le croisement et la mutation.
Exercices
LY_SII __ 148 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
1. Etant donné les situations suivantes, que l'étude du paradigme (dirigé, non surveillé, ou
renfort) est les la plupart approprié et pourquoi ?
3. Employer le même ensemble de données des exemples et grouper les données avec une
carte de dispositif de Kohonen.
Chapitre 6
Agents Intelligent
En ce chapitre nous explorons le rapport entre l'intelligence artificielle et les
agents intelligents en détail. Nous montrons comment des matières d'intelligence
artificielle telles que la représentation de connaissance, le raisonnement, et
l'étude peuvent être combinées pour construire les agents intelligents. Nous
discutons les conditions pour les agents intelligents autonomes comprenant la
perception, le raisonnement, et la capacité d'agir. Nous décrivons une des
architectures multiagent les plus tôt, systèmes de tableau noir, et puis discutons
quelques idées courantes au sujet des communications d'agent, spécifiquement la
langue de question et de manipulation de la connaissance. En conclusion, nous
regardons des systèmes où les agents intelligents multiples communiquent,
coopèrent, et concurrencent.
De l'IA à AI
Dans les chapitres précédents, nous avons exploré les matières principales dans l'intelligence
artificielle, les techniques de recherche, les représentations de connaissance, les algorithmes
de motif, et l'étude. Dans le chapitre préliminaire, nous avons décrit comment des agents
intelligents peuvent être employés pour renforcer le potentiel des applications et pour aider
des utilisateurs à obtenir leur travail effectué. Dans cette section, nous précisons les liens
explicites entre les technologies de base d'AI et les comportements correspondants d'agent
intelligent. Nous précisons également les dispositifs de la langue de Java qui sont applicables
ou importants pour mettre en application ces comportements.
En chapitre 2, nous avons discuté la résolution des problèmes état-basée using la recherche.
En chapitre 3, nous avons exploré plusieurs formes de représentation de connaissance. Pour
nos agents intelligents, la représentation de connaissance est une question cruciale. Comme
dans n'importe quelle application d'AI, ce qu'on s'attend à ce que notre agent fasse, et dans
quel domaine, aura un impact significatif sur le type de représentation de connaissance que
nous devrions employer. Si notre agent a un nombre limité de situations qu'il doit répondre à,
hardcoding peut-être l'intelligence dans le code procédural de programme est la solution. Si
notre agent doit construire ou employer les modèles sophistiqués du domaine de problème et
résoudre des problèmes à différents niveaux d'abstraction, alors les armatures ou les filets
sémantiques sont la réponse. Cependant, si l'agent doit répondre à des questions ou produire
de nouveaux faits des données existantes, alors de la logique d'attribut ou si alors des règles
sont considérées. Dans beaucoup d'applications, nous devrons employer un mélange de ces
représentations de connaissance. Si notre agent va agir l'un sur l'autre avec d'autres agents et
doit partager la connaissance puis il devrait pouvoir probablement lire et écrire des données
de KIF.
présenter les problèmes de sécurité qui peuvent rendre explicite si puis des règles moins
souhaitables qu'une autre représentation de connaissance. Par exemple, les attributs de la
« boîte noire » d'un réseau neurologique, qui sont vus comme inconvénient d'une perspective
symbolique traditionnelle d'AI, deviennent un avantage distinct une fois vus d'une position
avantageuse de connaissance-sécurité.
Si l'étude est une fonction souhaitable dépend du domaine que l'agent intelligent fonctionnera
dedans, aussi bien que l'environnement. Si l'agent est longévital et effectuera les tâches
semblables beaucoup de fois pendant sa vie, alors l'étude peut être employée pour améliorer
son exécution. Mais ajouter l'étude serait surpuissant si l'agent sera employé seulement de
temps en temps. Si nous savons les principes de base principaux, pourquoi est-ce que les
programmer pas simplement dans l'agent et il être capable de se comporter bien dès le début,
au lieu d'ajouter la complexité et les coûts se sont associés aux algorithmes d'étude ? Mais il y
a beaucoup de domaines, tels que les aides personnels, où nous ne savons pas les préférences
d'utilisateur à l'avance. Une option est de demander à l'utilisateur d'énoncer explicitement ce
que sont ses préférences. Mais ceci peut être pénible pour l'utilisateur et, selon le domaine,
peut être impossible. Souvent, les gens savent ce qu'ils l'aiment mais ne peuvent pas aisément
exprimer en mots. C'est où l'avantage d'un agent de étude apprête. En observant ce que
l'utilisateur fait dans certaines situations, l'agent intelligent peut apprendre ce que l'utilisateur
préfère d'une manière beaucoup moins importune qu'en jouant un jeu de « 20 questions. »
S'il y aura un grand nombre d'incertitude dans le domaine de problème, alors using les réseaux
bayésiens ou si alors les facteurs de règles avec certitude peuvent être appropriés. Si l'agent
doit trouver une réponse optimale, alors état-basées des techniques de recherche ou des
algorithmes génétiques biologiquement basés devraient être employés. Des méthodes de
planification, de ce type discutées en chapitre 4, s'appelleraient pour si l'agent doit exécuter
une série complexe d'actions. L'étude de renfort a pu également être employée pour apprendre
des ordres des opérations exigées pour atteindre un but.
Pour récapituler, toutes les techniques d'intelligence artificielle discutées dans ce livre
s'appliquent aux agents intelligents. Mais, elles sont juste des outils qui doivent être employés
par un concepteur habile pour ouvrer une solution qui répond aux besoins d'une application
spécifique. Dans le code de Java d'exemple, nous fournissons les blocs constitutifs simples
pour commencer votre exploration des agents intelligents. Dans la partie, nous combinerons
ces éléments de base dans une architecture pour produire un comportement plus puissant.
Dans les prochaines sections, nous regardons des possibilités, la perception et l'action
spécifiques d'agent, et discutons les conditions qu'ils placent sur des réalisations d'agent
intelligent.
Perception
Pour qu'un agent de logiciel prenne une certaine mesure intelligente, il d'abord doit pouvoir
percevoir ce qui continue autour de lui, pour avoir une certaine idée de l'état du monde. Pour
des animaux, ce problème est résolu par les sens du contact, de l'odeur, du goût, de l'audition,
et de la vue. Le prochain problème est de ne pas obtenir accablé par le jet constant
d'information. En raison du grand nombre d'entrée sensorielle crue nous obtenons, une des
premières choses que les humains apprennent est de filtrer dehors et ignorer les entrées qui
sont prévues ou habituelles. Nous développons un modèle interne du monde, de ce que les
conséquences prévues sont quand nous prenons une mesure. Tant que les choses vont comme
LY_SII __ 151 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
prévu, nous pouvons passer sans prêter trop d'attention (par exemple, quelqu'un conduisant
une voiture tout en parlant à un téléphone mobile). Mais nous également avons appris à nous
concentrer immédiatement sur les changements inattendus de l'environnement, tel qu'une
voiture apparaissant dans notre vision périphérique tout en entrant dans une intersection.
Notre agent intelligent doit avoir une source équivalente d'informations sur le monde en
lequel elle vit. Cette information entre par ses sondes, qui des mai ou mai ne pas être fondu
dans le monde physique. Notre agent intelligent n'a pas besoin d'avoir des sens de la même
manière que nous faisons, mais il doit encore pouvoir recueillir des informations au sujet de
son environnement. Ceci pourrait être fait activement, en envoyant des messages à d'autres
agents ou systèmes, ou il pourrait être fait passivement en recevant un jet des messages
d'événement du système, de l'utilisateur, ou d'autres agents. Juste comme des personnes,
l'agent de logiciel doit pouvoir distinguer les événements normaux (mouvements de souris)
des événements significatifs (double-click sur une icône d'action). Dans un environnement
moderne de GUI tel que Windows ou Macintosh, l'utilisateur produit d'un jet constant des
événements au système fondamental de fenêtrage. Nos agents peuvent surveiller ce jet et
doivent identifier des ordres des actions d'utilisateur de base (le mouvement de souris, font
une pause, cliquent, mouvement de souris, pause, double-click) en tant que signalisation d'un
certain événement ou action d'utilisateur sémantique à plus grande échelle.
Naturellement, nous pouvons concevoir nos agents et leurs messages de telle manière qu'ils ne
doivent pas être très clairvoyants. Nous pouvons exiger de l'utilisateur de dire explicitement à
notre agent quoi faire et comment le faire. Les événements qui sont produits pourraient
contenir toute l'information que l'agent doit déterminer l'état actuel et l'action appropriée.
Cependant, une des raisons principales que nous voulons et les agents intelligents du besoin
est de libérer l'utilisateur de devoir être si explicites. La définition de l'ordre des actions
nécessaires pour qu'un ordinateur accomplisse une tâche, dans le détail sanglant, n'est pas
amusement (elle programme !). C'est la puissance et le plaisir de la délégation à d'autres.
Vous pouvez dire, « programmer un voyage à Raleigh, » et à votre agent l'obtient fait.
Si la perception est la capacité d'identifier des modèles, et notre agent reçoit ses entrées
comme jets des données, alors nous écrivons le royaume de l'étude de machine et de la
reconnaissance des structures. L'étude est non seulement utile pour adapter le comportement,
il est également tout à fait maniable quand nous voulons identifier des changements de notre
environnement. Un système d'étude peut associer certains états du monde à certaines
situations. Ces situations peuvent être normales et prévues, ou elles peuvent être originales et
inattendues. Simplement la notation de l'occurrence des événements et alors le calcul de la
probabilité ou de la probabilité d'un événement ou d'une situation peuvent ajouter la fonction
utile à un agent. La construction d'une table ou d'une carte entre ces états et l'action associée
est encore meilleure. Des algorithmes d'étude dirigés, tels que les réseaux neurologiques et les
LY_SII __ 152 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
arbres de décision, peuvent être employés pour faire automatiquement ces associations. De
nouveau, si nous savons toutes les situations notre agent peut entrer dans avant que nous
l'envoyions dehors dans le Cyberspace, puis nous pouvons juste construire ceci dans sa base
de connaissance. Mais dans un environnement complexe avec un grand nombre de situations
possibles, l'étude peut être la seule manière d'aller.
Action
Une fois que notre agent a clairvoyant identifié qu'un événement significatif s'est produit, la
prochaine étape est de prendre une certaine mesure. Cette action pourrait être de se rendre
compte qu'il n'y a aucune action à prendre, ou elle pourrait être d'envoyer un message à un
autre agent pour prendre une mesure en notre nom. Comme des personnes, les agents agissent
par des effecteur. Pour des personnes, un effecteur est nos muscles, quand nous prenons une
mesure physique dans le monde. Ou nous pouvons agir par la parole (using différents
muscles) ou par l'envoi de l'email (différents muscles encore). Par communication avec
d'autres personnes, nous pouvons les faire agir et changer l'environnement.
Mais supposer que nous prenons une mesure en donnant une instruction au du système
d'exploitation ou à une application. Supprimer un dossier. Envoyer l'email. Supposons-nous
que l'action a accompli ? Changeons-nous notre modèle courant de l'état du monde ? Que si
nous demandons un autre agent font quelque chose pour nous ? Est-il prudent de penser que
tout fonctionnera correctement (l'agent est-il digne de confiance et exempt d'erreurs, le
serveur de réseau est-il en fonctionnement, la transaction va-t-il à travers le fil) ? Ou,
adoptons-nous la position cynique que la loi de Murphy est toujours en effet ? La réponse est,
« il dépend. » Juste comme nous savons que si nous mettons un livre vers le bas, il sera là la
prochaine fois que nous marchons près, si notre agent prend une mesure directement sous sa
commande, nous pouvons la considérer probablement faite. Mais quand nous traitons des
intermédiaires, si d'autres agents ou systèmes inconnus, puis quelques précautions
supplémentaires et la vérification sont probablement en règle.
Systèmes de Multiagent
Jusqu'ici en ce chapitre, nous avons regardé de quel agent intelligent simple doit être capable
pour aider un utilisateur à obtenir son travail effectué. Mais, juste comme nous avons des
compagnies où les talents uniques de beaucoup de personnes sont combinés pour résoudre des
problèmes, nous pouvons avoir les agents intelligents multiples travailler ensemble vers un
objectif commun.
Toutes les fois que deux autonomes, les êtres modérément intelligents essayent de
communiquer, les problèmes surgissent. D'abord, ils doivent parler la même langue qui
emploie le même ensemble de marques ou de symboles. Puis, ils doivent convenir sur ce que
signifient ces symboles. Ils doivent également développer une manière d'échanger des
communications dans cette langue. Ils ne peuvent pas tous les deux parler en même temps. Ils
ne peuvent pas tous les deux essayer d'écrire sur la même page en même temps. Ce sont tous
des problèmes fondamentaux dans la communication, et les premières applications
intelligentes artificielles qui ont essayé d'employer les agents multiples ont dû traiter et
résolvent chacun de ces problèmes. Dans la prochaine section, nous décrivons des systèmes
de tableau noir, la première architecture multiagent d'application d'AI.
LY_SII __ 153 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Tableaux noirs
Tandis que les tableaux noirs et la craie sont maintenant légèrement hors de la mode,
remplacée par des whiteboards et sèchent des marqueurs d'effacement, ils sont toujours une
métaphore utile pour une architecture importante d'intelligence artificielle. L'architecture de
tableau noir a été présentée la première fois dans le projet de reconnaissance de la parole de la
rumeur II (Erman et autres 1980). Elle a comporté un système avec des sources multiples de
la connaissance ou les agents indépendants, chacun avec un domaine spécifique d'expertise se
sont rapportés à l'analyse de la parole. Le tableau noir est une structure de données qui est
employée comme mécanisme général de communication pour les sources multiples de la
connaissance et est contrôlée et arbitrée par un contrôleur (Jagannathan, et autres 1989).
Pendant que chaque agent travaille à sa partie du problème, il regarde au tableau noir pour
prendre la nouvelle information signalée par d'autres agents, et elles, à leur tour, signalent
leurs résultats au tableau noir. Ainsi, tout comme un tableau noir dans un environnement de
salle de classe, le tableau noir est un dispositif de partage d'informations, avec les auteurs
multiples et les lecteurs multiples. Les agents, comme des étudiants, chaque travail à leur
propre rythme sur les problèmes qui sont de la plupart d'intérêt à eux ou où ils ont la
connaissance à appliquer, et ajoutent l'information au tableau noir quand ils peuvent. D'autres
agents emploient cette information pour promouvoir leur propre travail. Ainsi, l'architecture
de tableau noir permet aux agents multiples de travailler indépendamment et coopérer à
résoudre un problème.
Le modèle de tableau noir est une généralisation de l'architecture utilisée dans la rumeur II.
C'est une technique de résolution des problèmes opportuniste parce qu'à chaque cycle
opératoire n'importe quel genre de méthode de raisonnement peut être employé. Un modèle
d'événement est employé pour signaler quand des modifications sont apportées au tableau noir
et pour informer les sources ou les agents de la connaissance que quelque chose a changés. Un
événement pourrait déclencher l'activation d'un ensemble d'agents ou le contrôleur pourrait
dynamiquement déterminer quel agent à commencer. Le contrôleur limite également l'accès
au tableau noir de sorte que deux agents n'essayent pas d'écrire sur le même espace en même
temps.
Un point final concernant des systèmes de tableau noir est que les sources ou les agents de la
connaissance sont très étroitement accouplés par la structure de données de tableau noir et ses
interfaces. Si vous établissez une grande application simple et voulez modulariser les bases de
connaissances, alors les tableaux noirs sont très bien. Cependant, si vous voulez un
environnement où les agents avec les structures très différentes et sans la connaissance d'un
tableau noir peuvent fonctionner ensemble, nous avons besoin des interfaces plus formelles
comme ceux décrits dans la prochaine section.
Communication
Quand nos agents doivent parler entre eux, ils peuvent faire ceci d'une série de manières. Ils
peuvent parler directement entre eux, s'ils parlent la même langue. Ou ils peuvent parler par
un interprète ou le facilitant, étant donné qu'ils sachent parler à l'interprète, et à l'interprète
peut parler à l'autre agent.
LY_SII __ 154 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
KQML
Des messages de KQML s'appellent les performatives. Chaque message est prévu pour
effectuer implicitement une certaine action spécifique. Il y a un grand nombre de
performatives définis dans KQML, et la plupart d'appui de systèmes agent-basé seulement un
petit sous-ensemble. Les performatives, ou les types de message, sont des mots réservés dans
KQML. Using des performatives, les agents peuvent demander d'autres agents l'information,
dire à d'autres agents des faits, souscrire aux services des agents, et offrir leurs propres
services.
(ask-one
:sender joe
:content (real price = sun.price())
:receiver stock-server
:reply-with sun-stock
:language java
:ontology NYSE-TICKS)
Deux agents qui veulent communiquer using KQML ont besoin des services d'un facilitant ou
du marieur de KQML (Kuokka et Harada 1995). Les agents communiquent avec le marieur
employant les messages standard de KQML. Ils peuvent s'enregistrer comme fournisseur des
services ou de l'information using la publicité performative. Les agents peuvent également
demander au marieur de recommander d'autres agents using la recommandation, recruter, et
des performatives de courtier. Le marieur fournit un réunion-endroit centralisé pour des
agents, et établit une communauté où les agents peuvent agir l'un sur l'autre. Noter que le
marieur ne peut pas garantir pour la fidélité des agents qui annoncent leurs services, ni
garantit qu'un agent peut fournir une information spécifique. Néanmoins, le marieur joue un
rôle important dans un système multiagent. L'alternative serait pour que chaque agent
questionne chaque autre agent toutes les fois qu'elle a dû collaborer.
Agents de coopération
Le point de droit pour avoir les agents multiples coopèrent à réaliser un travail est irrésistible.
Pourquoi avoir un agent slave loin quand nous pouvons avoir cinquante fonctionner ensemble
pour accomplir la même tâche ? Quel est plus, pourquoi a une base et application de
connaissance énormes d'intelligence artificielle si nous pouvons résoudre le même problème
en construisant et le maintien d'une collection avec des agents beaucoup plus petits et plus
simples ? Naturellement, l'idée de diviser un problème en plus petits morceaux n'était pas une
invention d'intelligence artificielle. Diviser et conquérir est une stratégie militaire antique.
Dans de l'informatique, c'était l'un des principes de base de la conception structurée de haut en
bas, utilisés dans tout de COBOL à Pascal. Cependant, avec des agents, les avantages des
petites, indépendantes sources de la connaissance doivent être pesés contre les inconvénients
considérables de présenter une barrière linguistique entre eux. Mais dans plusieurs domaines,
les avantages ont loin été supérieurs aux coûts.
Car les modèles de client/serveur et de l'informatique répartie ont évolué pendant les deux
dernières décennies, les problèmes avec la gestion-système sont devenus évidents. Les
directeurs de système, qui ont été employés aux moniteurs d'exécution qui ont fourni des vues
claires de l'état du centre serveur centralisé, ont eu un temps difficile manipuler les
applications qui ont fonctionné à travers des réseaux des postes de travail. La solution était de
déployer des agents de moniteur de système sur chacun de ces systèmes distribués. Un
contrôleur centralisé pourrait communiquer (habituellement par le vote) avec l'agent du
moniteur à distance pour obtenir l'information sur le statut de chaque ordinateur à distance.
L'application de gestion de système distribué a pu intégrer cette information pour fournir une
vue d'ensemble de l'état actuel du système. Tout en commençant en tant qu'agents très
simples, ces agents de moniteur ont élevé un temps fini plus sophistiqué.
systèmes de réservation de ligne aérienne pour trouver le meilleurs prix et itinéraire. Sous une
forme plus complexe, l'acheteur doit avoir affaire avec un agent de vente, qui a son propre
ordre du jour (pour gagner autant argent comme possible par transaction pour son
propriétaire) et stratégies. Dans ce contexte de marché, les agents coopèrent à servir les
intérêts des deux parties. En même temps, il y a un courant de fond de la concurrence. Le
système de Kasbah développé à MIT Media Lab est un exemple de ce genre de marché
électronique (Chavez et Maes, 1996).
Les systèmes de conception de Multiagent sont un autre secteur où les agents indépendants de
multiple ont prouvé leur valeur (Lander 1997). Dans un système de conception de
collaboration, beaucoup de concepteurs doivent travailler aux morceaux de recouvrement de
la conception en même temps. Un changement d'une part peut effectuer plusieurs autres. Le
système de conception entier inclut les concepteurs humains aussi bien que les agents
intelligents, ainsi les interactions homme-ordinateur sont importantes. Souvent, des agents
d'aide personnel sont employés pour fournir l'interface entre les concepteurs et les agents dans
le système. Un aspect important des systèmes de conception multiagent est que chaque agent
intelligent a sa propre perspective sur ce qu'est une « bonne » ou « optimale » conception,
selon son domaine de spécialisation. Ce n'est pas très différent des équipes de développement
croix-fonctionnelles. Ainsi, chaque agent doit être disposé à compromettre afin de réaliser une
meilleure conception globale ou globale. Ceci signifie également qu'il y a quelque part un
agent qui peut fournir une certaine mesure de la qualité de la conception globale et peut
arbitrer des conflits entre les agents plus spécialisés.
Agents de concurrence
Dès que nous aurons des agents qui font notre offre, d'autres personnes auront des agents pour
faire le leur. Notre agent veut obtenir la meilleure affaire pour nous. D'autres agents veulent
obtenir la meilleure affaire pour leurs propriétaires. À qui agent gagne ? Celui probablement
avec la plupart d'intelligence, connaissance la plus spécialisée au sujet de la tâche qu'elle
essaye d'effectuer, système de raisonnement le plus puissant pour s'appliquer cette
connaissance à la résolution des problèmes dans le domaine, et, dans toute la probabilité, celui
qui peuvent apprendre de l'expérience et devenir meilleurs avec le temps.
Ceci suppose naturellement que nous avons un terrain de jeu de niveau. Il ne serait pas juste si
votre agent était sur un serveur étant en pourparlers avec un autre agent qui pourrait accéder à
une grande base de données locale d'information alors que votre agent ne pourrait pas. Ou, si
votre agent était balayé par le serveur, et des informations sur votre position de négociation
(prix, stratégies, règles, etc.) a été confié à l'autre agent. Enverriez-vous votre agent dehors sur
l'Internet si vous pensiez que vous pourriez perdre ou être tiré profit tellement facilement ?
Probablement pas. À notre avis, il devra y avoir les marchés bloqués d'agent, où les agents
s'enregistrent et sont garantis d'avoir l'égalité d'accès aux services et à l'information de
serveur.
Il y a également concurrence entre les agents à l'moins niveau direct. Par exemple, supposer
que deux travailleurs intellectuels aux compagnies de concurrence sont tous deux qui essayent
de finir une proposition de projet pour un client. Si on a un ensemble d'agents intelligents qui
peuvent l'aider à trouver les informations priées dans la moitié du temps en tant que son
concurrent, cela lui donne un avantage compétitif. C'est juste une prolongation de l'utilisation
courante de la technologie de l'information d'aider une compagnie à gagner dans le marché.
LY_SII __ 157 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Quand chacun a les agents intelligents travailler pour eux, le gagnant sera celui avec les
meilleurs agents.
Résumé
En ce chapitre, nous avons exploré comment des techniques d'intelligence artificielle sont
employées pour construire les agents intelligents. Les questions principales sont :
Exercices
LY_SII __ 158 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
chapitre 7
Cadre d'agent du Intelligent
En ce chapitre, nous développons une architecture d'agent intelligent using des
techniques de conception orientée objectivement. Nous commençons par un
ensemble générique de conditions et les raffinons en jeu de caractéristiques. Nous
énonçons explicitement notre philosophie et buts de conception et considérons de
diverses solutions de rechange de conception et d'exécution sous ces contraintes.
Nous explorons comment des agents intelligents peuvent être employés pour
augmenter les possibilités des applications traditionnelles et comment ils peuvent
servir de contrôleur à un groupe d'applications. Avec des modifications mineures,
nous réutilisons les fonctions d'intelligence artificielle que nous avons
développées dans Java dans la partie de ce livre.
Conditions
La première étape dans n'importe quel projet de développement de logiciel est la collection de
conditions de la communauté d'utilisateur prévue. Dans notre cas, ceci est rendu difficile
parce que nos lecteurs ne peuvent pas fournir ce genre de rétroaction jusqu'à ce que nous
ayons déjà conçu et ayons développé le produit (ce livre). Cependant, nous avons fait
quelques décisions évidentes au sujet de l'assistance et but prévu de ce livre, comme indiqué
par le titre. Nous allons développer les agents intelligents using Java. Nous allons également
fournir la capacité d'ajouter l'intelligence aux applications ou les applet écrits dans Java. Une
condition fondamentale additionnelle est que nous devrions réutiliser le code d'intelligence
artificielle que nous avons développé dans la partie 1.
Une autre condition est que notre cadre d'agent intelligent soit pratique. Non pratique dans le
sens que c'est code de produit-niveau prêt à mettre dans la production, mais parce que les
principes de base et la poussée de notre conception s'applique à résoudre des problèmes réels.
Tandis que la fourniture d'une expérience d'étude stimulante est un but, nous ne sommes pas
intéressés à explorer purement l'universitaire ou, plus exactement, les issues ésotériques. Si
vous comprennent ce que nous faisons et pourquoi nous le font, vous devriez pouvoir
employer ces techniques pour développer vos propres applications d'agent intelligent.
Le foyer sur la matière actuelle est une autre condition. C'est un livre concernant les agents
intelligents. Nous ferions le lecteur un service si nous dépensions des grands nombres de code
de communications se développant de temps, d'une base de données orientée objectivement,
ou d'un mécanisme pour exécuter des appels de procédure à distance. Nous essayerons de
maximiser la quantité de code traitant les agents intelligents, et réduisons au minimum le code
pas directement lié à la matière. En même temps, parce que c'est un livre concernant Java
programmant, nous voulons employer les dispositifs et les possibilités ont trouvé dans Java et
l'environnement de développement de JDK 1.1.
Après avoir dit juste le tout ceci, nous reconnaissons également cela qui fournit une interface
utilisateurs décente est également une condition. Heureusement, avec les environnements de
développement courants de Java, la fourniture d'un GUI utilisable n'est pas un problème
majeur. Nous utiliserons l'outil visuel de Symantec CafŽ pour créer ces interfaces. Puisque la
LY_SII __ 160 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
majeure partie du code de GUI est produite, nous ne dépenserons pas beaucoup d'heure ou
d'énergie discutant cet aspect de nos applications. Il y a certainement d'autres outils visuels de
constructeur qui peuvent produire du code de Java et elles pourraient être employées au lieu
du produit de Symantec.
La prochaine condition vient des auteurs, qui dépensent également les livres de
programmation de beaucoup de lecture de temps. Nous ne créerons pas une conception
complexe et ne la décrirons pas dans le détail minutieux. Tandis que ce serait un exercice
intéressant pour nous, nous doutons qu'il te fournisse la valeur, nos lecteurs. Nous appellerons
ceci la « subsistance il » condition simple et stupide, et espérons qu'explicitement l'énumérant
ici shame nous dans suivre cette maxime quand nous obtenons trop emportés.
La dernière condition est que notre architecture doit être assez flexible pour soutenir les
applications présentées dans les trois prochains chapitres. Comme prévision, nous
construirons les agents intelligents pour manipuler la gestion d'un PC, de l'information filtrant
au-dessus de l'Internet, et des transactions multiagent simples de commerce électronique.
Pour récapituler les conditions, nous voulons une architecture simple pourtant flexible qui est
concentrée sur des questions d'agent intelligent. Elle doit être pratique ainsi elle peut résoudre
des problèmes réalistes et doit avoir une interface utilisateurs décente ainsi ses fonctions et
limitations seront tout à fait évidentes aux utilisateurs. Dans la prochaine section, nous parlons
de nos buts d'une perspective technique.
Buts de conception
Les conditions viennent de nos utilisateurs et nous indiquent quelles fonctions ou propriétés
notre produit doit avoir afin d'être réussi. Avoir un ensemble validé de conditions est utile,
parce qu'il concentre notre énergie sur la substance importante. Il est juste comme important
pour avoir un ensemble clair de buts de conception que nous pouvons employer pour guider
les décisions techniques qui doivent être prises pendant que nous développons la solution qui
répond à ces exigences. Juste comme avec des conditions, nous devons explicitement énoncer
nos buts et prétentions de conception.
Il y a quelques issues fondamentales qui conduiront notre conception. Le premier est que nous
pouvons regarder nos agents intelligents ou en tant qu'ajouter la valeur à une application
autonome simple, ou en tant que communauté libre des agents qui agissent l'un sur l'autre les
uns avec les autres et d'autres applications. Le premier est une vue application-centrale des
agents, où les agents sont des aides à la demande (et donc des utilisateurs de l'application).
Cette approche est moins la complexe parce que nous pouvons regarder l'agent comme
prolongation simple de la fonctionnalité d'application. Par la fourniture notre agent intelligent
fonctionne comme cadre orienté objectivement, nous peut facilement ajouter le comportement
intelligent à n'importe quelle application de Java.
La deuxième approche est agent-centrale, où les agents appellent les projectiles et le moniteur
et conduisent les applications. Ici notre directeur d'agent est une application à son propre chef
et doit se connecter par interface à d'autres applications qui sont conduites par les agents. La
complexité ici est que nous devons définir un mécanisme générique pour des communications
d'application par notre directeur d'agent. Une méthode est d'exiger de chaque application de
modifier son code pour être « agent-avertie. » Un autre est pour que nous fournissent une
LY_SII __ 161 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
manière commune de se connecter par interface aux interfaces de programmation API pour
commandes Tempus-link uniques.
Le cadre de CIAgent doit être facilement compréhensible et franc pour employer. Le but
primaire de développer ce cadre est d'illustrer comment des agents intelligents et les
différentes techniques IA Peuvent être employés pour augmenter des applications. Notre
modèle de codage sera franc. Les membres de données seront publics et des fonctions
d'accédant seront employées seulement quand l'encapsulation stricte est exigée. Ce n'est pas
code de commercial-niveau. Le code de blindage à l'épreuve des balles peut parfois faire
même la logique simple sembler complexe. Nos applications fonctionneront comme conçu,
mais elles ne pourront pas manipuler toutes les données d'entrée ou conditions d'erreur
inattendues.
Nous construirons le cadre d'agent de sorte que la communication interagent puisse être
soutenue aussi bien que la mobilité de nos agents à travers des réseaux. La flexibilité inclut
également la capacité d'ajouter facilement le soutien de nouvelles applications, de techniques
IA, Et d'autres dispositifs.
Caractéristiques fonctionnelles
Dans cette section, nous prenons les conditions et nos buts de conception, et les transformons
en liste de fonctions qui satisfont ces conditions et buts. Ceci définit ce que nous devons
construire. Les caractéristiques fonctionnelles sont un contrat entre l'équipe de développement
et la communauté d'utilisateur. Voici la fonctionnalité que nous pensons que nous avons
besoin :
1. Il doit être facile d'ajouter un agent intelligent à une application de Java existante.
2. Un outil graphique de construction doit être disponible pour composer des agents
hors d'autres composants de Java et d'autres agents.
3. Les agents doivent soutenir des possibilités de événement-traitement relativement
sophistiquées. Notre agent devra manipuler des événements du monde extérieur,
d'autres agents, et d'événements de signal aux applications extérieures.
4. Nous devons pouvoir ajouter la connaissance de domaine à notre agent using si puis
des règles, et soutenons le traitement basé sur les règles vers l'avant et en arrière avec
des sondes et des effecteur.
5. Les agents doivent pouvoir apprendre à faire la classification, le groupement, et la
prévision using des algorithmes d'étude.
6. Des applications de Multiagent doivent être soutenues using a KQML-comme le
protocole de message.
7. L'agent devrait être persistant. C'est-à-dire, une fois qu'un agent est construit, il doit
y a une manière de la sauver dans un dossier et de recharger son état à un temps
postérieur.
Maintenant que nous avons spécifié les fonctions que notre architecture d'agent intelligent
doit fournir, nous devons prendre nos décisions de conception. Nous accepterons les points de
vue de fonction dans l'ordre et discuterons les diverses issues et différences que nous devons
faire.
LY_SII __ 162 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
1. Il doit être facile d'ajouter un agent intelligent à une application de Java existante.
La manière la plus facile pour que nous ajoutent un agent à une application existante
est de faire puis appeler l'application instancier et configurer l'agent et les méthodes de
l'agent comme routines de service. Que la manière l'application est toujours dans la
commande, et elle peut employer les fonctions intelligentes comme appropriées. C'est
facile, mais est à peine ce ce que nous considérerions un agent intelligent. C'est
intelligence incluse, mais il n'y a aucune autonomie. Une autre possibilité est de faire
puis le commencer l'application instancier et configurer l'agent et vers le haut dans un
fil séparé. Ceci donnerait à l'agent de l'autonomie, bien qu'il fonctionne dans l'espace
du procédé de l'application. L'application pourrait rapporter à l'agent si nécessaire, et
l'agent rapporterait quand il était traitement fait de sorte que l'application ait pu
continuer. Une troisième possibilité est d'avoir la course d'agent dans un fil séparé,
mais emploie des événements pour communiquer entre l'application et l'agent. Dans
Java, ceci peut être fait using l'observateur/cadre observable. L'agent serait un
observateur, et toutes les fois qu'on a annoncé l'agent qu'un événement s'est produit, il
serait exécuté. Un inconvénient de cette approche est que l'application devrait être une
sous-classe de chose observable.
2. Un outil graphique de construction doit être disponible pour composer des agents
hors d'autres composants de Java et d'autres agents. Il y a des instruments de
développement graphiques tels que Symantec VisualAge visuel de CafŽ et d'IBM
pour Java qui te permettent de construire des applications using « construction une
métaphore de pièces ». Cependant, le dégagement de JDK 1.1 de Java fournit des
possibilités de composant de base par son paquet de java.beans. JavaBeans est un
modèle composant de Java qui permet aux fonctions de logiciel d'être traitées comme
« partie » qui peuvent être remontées pour construire une application. Chaque
JavaBean a une interface bien définie qui permet à un outil visuel de constructeur de
manoeuvrer cet objet. Il a également une interface d'exécution définie qui permet des
applications consistées en JavaBeans pour courir. Un autre dispositif gentil des
haricots est qu'elles peuvent être nichées. Ce répond à notre exigence pour que la
capacité compose des agents hors d'autres agents. Ceci nous permet de développer les
agents pour un but particulier qui peuvent être réutilisés dans d'autres agents de plus
haut niveau. Par exemple, nous pouvons avoir des agents de bas niveau qui emploient
les réseaux neurologiques pour l'étude et les agents à niveau élevé qui emploient des
règles pour déterminer quelles actions à prendre. Cette fonction est rudement
équivalente au modèle de conception composée comme spécifique par Gamma et
autres (1995). Le BeanBox fait partie du kit de développement d'haricot et fournit à un
rudimentaire, mais efficace, environnement graphique de défaut pour travailler des
haricots. Nous pouvons employer le BeanBox en tant que notre environnement visuel
de construction.
3. Les agents doivent soutenir des possibilités de événement-traitement relativement
sophistiquées. Notre agent devra manipuler des événements du monde extérieur,
d'autres agents, et d'événements de signal aux applications extérieures. Le dégagement
de JDK 1.1 comporte un nouveau modèle de événement-traitement puissant appelé le
modèle d'événement de délégation. Ce nouveau cadre a été conduit réellement par les
conditions du modèle de composant de JavaBeans. Ce modèle est basé sur des sources
d'événement et des auditeurs d'événement. Il y a beaucoup de différentes classes des
événements avec différents niveaux de granularité. Nous emploierons le modèle
d'événement de JavaBeans dans notre cadre d'agent.
LY_SII __ 163 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
4. Nous devons pouvoir ajouter la connaissance de domaine à notre agent using si puis
des règles, et soutenons le traitement basé sur les règles vers l'avant et en arrière avec
des sondes et des effecteur. Les classes de RuleBase, de règle, et de RuleVariable
que nous avons développées en chapitre 4 peuvent être employées dans nos agents
pour fournir inferencing basé sur les règles vers l'avant et en arrière. Nous devrons
prolonger la fonctionnalité aux sondes et aux effecteur de soutien. La raison principale
de fournir cette fonctionnalité est de fournir une manière non programmeuse pour que
les utilisateurs spécifient des conditions et des actions. Si nous construisons un
rédacteur de propriété de JavaBeans pour notre classe de RuleBase, n'importe quel
utilisateur pourrait facilement construire un ensemble avec de RuleVariables et de
règles pour exécuter la logique derrière un comportement d'agent intelligent. Nous
fournissons cette fonctionnalité, mais ne l'exploitons pas. C'est-à-dire, la tâche de
développer un rédacteur de propriété pour l'usage dans un environnement de
développement visuel d'haricot est laissée comme exercice pour le lecteur.
5. Les agents doivent pouvoir apprendre à faire la classification, le groupement, et la
prévision using des algorithmes d'étude. En chapitre 5, nous avons conçu et avons
développé des classificateurs d'arbre de décision, et des algorithmes neuraux de
groupement et de prévision dans Java. Nous pouvons employer les classes de
DecisionTree, de BackPropNet, et de KMapNet pour fournir ces fonctions à nos
agents.
6. Des applications de Multiagent doivent être soutenues using a KQML-comme le
protocole de message. Afin de fournir cette fonctionnalité, nous devrons retourner au
drawingboard, et fournir un agent qui peut gérer des tâches comme un facilitant ou le
marieur de KQML. Nous voudrions employer nos possibilités existantes de règle pour
aider à fournir cette fonction, si possible. Nous pouvons employer le modèle
d'événement de JavaBean pour fournir le mécanisme de communication entre les
agents et le facilitant et pour définir nos propres objets d'événement pour tenir le
contenu de message.
7. L'agent devrait être persistant. C'est-à-dire, une fois qu'un agent est construit, il doit
y a une manière de la sauver dans un dossier et de recharger son état à un temps
postérieur. La fabrication en série de 1.1 soutien de JDK de Java objecte. En outre, le
cadre de JavaBeans fait l'économie et le chargement des objets très faciles à faire. En
fait, tous membres de données qui ne sont pas explicitement déclarés car la charge
statique ou la coupure sera sauvée dehors à un dossier. Tellement voici un autre
avantage d'employer le modèle composant de JavaBean en tant que notre base.
Le cadre de CIAgent
Tout en essayant de ne pas être trop mignons, nous avons choisi le CIAgent nommé pour
notre cadre d'agent intelligent, où CIAgent représente « construire les agents intelligents. »
Beaucoup d'autres noms se sont suggérés à nous, mais ceci semble comme un choix
raisonnable, donné le titre du livre. S'il vous branche vraiment sur table d'écoute, nous
espérons qu'il n'interfère pas votre arrangement et utilisation de notre conception.
Pour récapituler les décisions que nous avons prises dans la section précédente, nous vont
construire nos agents intelligents ainsi ils peuvent agir l'un sur l'autre avec le modèle de
composant de JavaBeans. Cette décision de conception, combinée avec la réutilisation du
code de la partie de ce livre, nous permet de rencontrer la plupart de nos caractéristiques
fonctionnelles. Nous devons faire quelques perfectionnements à notre traitement de règle,
LY_SII __ 164 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
aussi bien que développons un facilitant pour nos applications multiagent. Cependant, nous
allons bien sur notre chemin à fournir un cadre utilisable d'agent intelligent.
La prochaine étape est d'esquisser dehors notre structure et interfaces de classe. Nous
commençons par une classe basse abstraite qui définit l'interface commune employée par les
éléments de notre architecture.
CIAgent est le nom de la classe basse qui définit une interface et un comportement de
programmation communs pour tous les agents dans notre cadre. En termes de modèles de
conception, CIAgent emploie une conception composée. Ceci signifie que nous pouvons
employer un CIAgent simple ou les composer dans des groupes, et traite toujours le groupe
comme si c'était un objet logique simple de CIAgent. Ce modèle de conception est très
puissant parce qu'il nous permet d'accumuler une hiérarchie de CIAgents using d'autres
classes spécialisées de CIAgent dans le processus.
La classe de CIAgent met en application l'interface praticable, qui exige que nos sous-classes
de CIAgent fournissent une méthode de run () qui peut servir de corps d'un thread. C'est le
mécanisme que nous employons pour donner à nos agents l'autonomie. Pour communiquer
avec l'autre CIAgents et tout autre JavaBeans, nous mettons en application l'interface de
CIAgentEventListener. Cette interface prolonge l'interface standard de Java EventListener
employée par tous les composants et JavaBeans d'AWT. Bien que nous ne prolongions
aucune classe de JavaBeans, la classe de CIAgent est un JavaBean, en vertu de notre interface
d'EventListener et du public, méthode de CIAgent() de constructeur de défaut de zéro-
argument (). Un vecteur des auditeurs tient tous les objets de Java qui mettent en application
l'interface de CIAgentEventListener et qui se sont enregistrés suivre la méthode
d'addCIAgentEventListener (). N'importe quel objet de CIAgent peut être la source
d'événement pour CIAgentEvents, et n'importe quel objet de CIAgent peut être un auditeur
enregistré pour ces événements. La classe de CIAgent fournit l'addCIAgentEventListener () et
les méthodes de removeCIAgentEventListener () de sorte que l'autre CIAgents puisse être
ajouté à la liste d'avis d'événement de multicast. Ces méthodes approuvent pleinement
l'événement api de JavaBeans, ainsi CIAgents peut être câblé vers le haut using le BeanBox
ou n'importe quel outil visuel de constructeur qui soutient JavaBeans.
Chaque CIAgent a un membre ou une propriété de corde pour son name, et nous appliquons
les méthodes standard de JavaBean pour l'arrangement et obtenir le name par le BeanBox ou
tout autre outil visuel de constructeur. Nous employons la classe de JavaBean
PropertyChangeSupport pour faire au name une propriété de liage. Quand le name est
changé, on annoncera d'autres auditeurs.
Les autres méthodes que nous définissons incluent initialize () et remettent à reset () des
méthodes pour obtenir l'agent à un état KNOWN, et process () et des méthodes d'stop () pour
commencer le fil de agent-traitement ou l'arrêter. Noter que nous pourrions avoir employé la
LY_SII __ 165 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
méthode d'init() de Java comme défini dans la classe d'applet, mais nous avons choisi
d'éviter toutes les collisions nommées. En fait, nous pourrions facilement avoir prolongé notre
classe de CIAgent d'applet pour faire tous de nos applet de CIAgents. Le CIAgents fourni
dans ce livre a pu être facilement tourné dans des applet ou par subclassing un
awt.Composant ils pourraient être transformés en JavaBeans évident. Comme mis en
application ici, notre CIAgents sont les haricots invisibles, signifiant qu'ils peuvent être
employés dans l'environnement visuel de constructeur, mais ils ne représentent pas les
composants graphiques dans le GUI d'application.
L'exécution de Java de notre classe de CIAgent suit. Elle contient des membres et des
méthodes pour la gestion d'EventListeners et traitement d'événement, constructeurs d'objet,
soutien du traçage utilisé par nos applications d'agent dans les chapitres suivants, et l'appui de
fil d'agent.
synchronized(this) { l = (Vector)listeners.clone(); }
for (int i=0 ; i < l.size() ; i++) { // deliver the event
((CIAgentEventListener)l.elementAt(i)).ciaEventFired(e);
}
}
};
CIAgentEvent
Le CIAgentEvent est dérivé de la classe de Java EventObject, selon les exigences des
spécifications de JavaBeans. Les constructeurs de CIAgentEvent () prennent ou un paramètre
simple, une référence à l'objet envoyant l'événement, ou une paire de paramètres définissant la
source et un argument d'événement objecte. Nous définissons ceci comme objet de sorte que
les sous-classes de CIAgent puissent envoyer n'importe quel objet comme argument dans un
CIAgentEvent. Nous ne pouvons pas savoir à l'avance ce qui sera nécessaire dans une sous-
classe. En chapitre 10, nous emploierons cette flexibilité de définir a KQML-comme l'objet de
message.
CIAgentEventListener
Perfectionnements de RuleBase
Dans cette section, nous décrivons les perfectionnements à nos classes de règle. Nous
incluons le soutien pour des sondes et des effecteur dans les règles, et des faits en tant
qu'élément de la base de règle. Nous définissons deux interfaces de Java, sensor et effector,
pour soutenir cette fonction. Nous prolongeons également la classe de clause avec un
SensorClause et un EffectorClause. Notre appui est comme suit :
Pour soutenir des faits, nous ajoutons une nouvelle classe appelée Fact dont le constructeur
prend une clause simple comme paramètre. Un fait peut être une attribution d'une valeur à un
RuleVariable, à un appel de sonde, ou à un appel effecteur. Les faits sont définis en tant
qu'élément du RuleBase avec les autres règles. Mais les faits sont également enregistrés dans
le RuleBase. La méthode d'initializeFacts () s'appelle pour placer les faits avant qu'un cycle
inferencing soit exécuté.
};
L'interface effector permet à n'importe quelle class de s'appeler comme effecteur par une
Rule dans un RuleBase. Elle doit mettre en application l'interface en fournissant () une
méthode effectrice simple qui prend un Object, un nom effecteur (pour des cas où la classe de
mise en oeuvre peut soutenir les effecteur multiples), et un paramètre d'argument de corde.
Une exécution alternative qui peut être utile serait de soutenir un objet comme paramètre
d'argument.
}
};
L'interface de Sonsor se compose d'une Sonsor() simple de méthode qui prend trois
paramètres : l'objet (SensorClause) qui a appelé la méthode, le nom de la sonde pour
employer, et un RuleVariable dans lequel pour stocker les résultats, le cas échéant. La
méthode de Sonsor () renvoie une valeur booléenne.
Boolean check() {
if (consequent.booleanValue() == true) return null ;
if (lhs.value == null) {
RuleBase rb = ((Rule)ruleRefs.firstElement()).rb ;
object = (Sensor)(rb.getSensorObject(sensorName)) ;
truth = object.sensor(this, sensorName, lhs) ;
}
return truth ;
}
};
Le fragment suivant de code donne un exemple de la façon dont des sondes et les effector
pourraient être employés dans les véhicules RuleBase :
Résumé
LY_SII __ 171 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
En ce chapitre nous avons décrit le cadre d'agent intelligent de CIAgent. Les questions
principales incluent :
• Nous avons décrit nos conditions et buts à niveau élevé de conception et les avons
traduits en ensemble de caractéristiques. Ceux-ci inclus :
1. Il doit être facile d'ajouter un agent intelligent à une application de Java existante.
2. Un outil graphique de construction doit être disponible pour construire des agents.
3. Les agents doivent soutenir des possibilités de événement-traitement relativement
sophistiquées.
4. Nous devons soutenir le traitement basé sur les règles vers l'avant et en arrière avec
des sondes et des effecteur.
5. Les agents doivent pouvoir apprendre à faire la classification, le groupement, et la
prévision.
6. Des applications de Multiagent doivent être soutenues using a KQML-comme le
protocole de message.
7. Les agents doivent être persistants, permettant pour les sauver dans un dossier et
pour reconstituer leur état plus tard.
• Nous avons décrit la classe basse de CIAgent, la classe de CIAgentEvent, et
l'interface de CIAgentEventListener pour fournir l'appui pour les agents intelligents
utilisés dans les applications dans les chapitres suivants.
• Nous avons prolongé le notre si puis fonction de traitement de règle en ajoutant les
classes de faits, de SensorClause, et d'EffectorClause, et les interfaces d'effecteur et de
sondes. Ceci permet à nos règles d'appeler des fonctions aux conditions d'essai et
d'effectuer des actions.
Exercices
Chapitre 8
Application du PCManager
En ce chapitre, nous illustrons comment nous pouvons employer l'architecture
de CIAgent pour construire une application qui emploie les agents intelligents
pour aider un utilisateur avec la gestion de PC et les activités locales
d'application. Deux agents intelligents autonomes simples sont développés, un
sont basés sur un temporisateur et des autres qui observent le système de fichiers
de PC. Quand un événement de déclenchement se produit, les agents peuvent se
signaler, alertent l'utilisateur, ou exécutent une commande de système.
Introduction
La première application d'agent intelligent que nous développons est un aide personnel conçu
pour nous aider en contrôlant notre PC. Notre but est de fournir la fonctionnalité de base tout
en illustrant les notions générales exigées pour ce domaine. Nous développons deux nouveaux
agents intelligents en prolongeant la classe basse de CIAgent présentée en chapitre 7. La
classe d'application de PCManager fournit une interface utilisateurs graphique using le cadre
de Java AWT, et fournit l'interface à TimerAgents et à FileAgents pour nous aider à contrôler
les ressources dans notre PC.
Le schéma 8.2 montre l'AlarmDialog. Chaque alarme a un nom, un type, alarme monocoup
ou intervalle, et une action associée. Une alarme monocoup doit avoir la période des alarmes
spécifiques en heures et minutes. L'alarme d'intervalle exige les spécifications du nombre de
secondes entre les alarmes. L'utilisateur peut choisir parmi une de trois actions quand les feux
d'alarme. Elle peut alerter l'utilisateur par l'intermédiaire d'un AlertDialog. Elle peut exécuter
LY_SII __ 174 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Le schéma 8.3 montre le WatchDialog. Comme une alarme, une montre a un nom, un
paramètre pour spécifier le dossier ou l'annuaire à observer, la condition de déclenchement sur
le dossier, et l'action pour prendre quand le déclenchement se produit. Si l'utilisateur ne
connaît pas le chemin de nom de fichier ou d'annuaire, elle peut cliquer dessus le bouton
poussoir de lecture rapide et ouvrir un awt.FileDialog standard sur le système de fichiers de
PC. Les conditions de déclenchement incluent si le dossier est supprimé ou modifié, ou si sa
taille dépasse un seuil spécifique. Les montres soutiennent les mêmes trois actions que des
alarmes, alertes, exécutant des commandes, et signalant des événements. Quand l'utilisateur
clique l'OK sur le WatchDialog, un FileAgent est instancié et les paramètres d'utilisateur
sont passés à l'exemple. Le nom du FileAgent est placé au nom de montre.
Deux dialogues additionnels liés aux actions d'alarme et de montre sont employés dans cette
application. L'AlertDialog affiche un message alerte à l'utilisateur. L'ExecuteDialog donne
les résultats d'une action d'exécution. Les deux dialogues d'action permettent à l'utilisateur de
reconnaître eux en cliquant l'OK, ou de décommander l'alarme ou la montre avec le bouton
d'annulation. Ces dialogues sont montrés dans l'exemple dans la prochaine section.
Un exemple
Les fonctions de base ont fourni par Alarms et des montres peuvent être combinées pour
produire le comportement intéressant. Dans cette section, deux alarmes et une montre sont
employées pour illustrer ceci par exemple. Les alarmes seront employées pour copier un de
deux dossiers dans un dossier de cible. Ce dossier de cible sera le centre d'une montre. Quand
chacun des trois agents est en activité dans l'application de PCManager, le scénario est
comme suit :
Les figures suivantes montrent les dialogues de paramètre et l'alerte et exécutent des
dialogues produits par cet exemple. Les schémas 8.4 et 8.5 montrent les paramètres employés
pour installer le TimerAgents pour Alarm1 et Alarm2 respectivement. Le schéma 8.6 montre
les arrangements Watch1.
LY_SII __ 175 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Quand les trois agents sont créés ils commencent immédiatement à fonctionner. Le schéma
8.7 montre au PCManager le panneau principal quand tous les agents sont configurés et
fonctionnement. Pendant qu'Alarm1 va au loin, le TimeAgent exécute la corde de paramètre
spécifique qui copie le dossier test1.dat au-dessus de test.dat (le schéma 8.8). L'agent Watch1
réveille toutes les 15 secondes pour vérifier le statut du dossier de test.dat. Quand il voit que
le dossier a été modifié (il emploie la méthode de Java File.getLastChanged ()) qu'elle signale
une alerte. Cet AlertDialog est montré sur le schéma 8.9.
Maintenant que vous avez vu un exemple du PCManager dans l'action, nous prenons un œil
plus attentif à l'exécution des deux agents, et le cours d'application de PCManager.
Alarmes : Le TimerAgent
Notre premier agent, le TimerAgent, n'est pas très intelligent mais est certainement autonome
et fournit une fonction extrêmement utile. Un TimerAgent peut être employé pour placer les
alarmes monocoup pendant n'importe quelle heure spécifique, ou il peut être employé pour
mettre le feu aux alarmes récurrentes à intervalles spécifiques. Quand des conditions d'alarme
se produisent, le TimerAgent peut prendre une de trois mesures. Il peut montrer une alerte,
où un dialogue saute vers le haut sur l'écran pour informer l'utilisateur qu'une alarme de
temporisateur est allée au loin. Il peut exécuter une commande de système arbitraire ou
appeler un programme d'application sur le système, passant des paramètres au besoin. Le
TimerAgent peut également simplement mettre le feu à un CIAgentEvent pour signaler un
autre CIAgent ou tout autre objet de Java.
Nous fournissons un ensemble de méthodes d'accédant pour chacune de ces propriétés pour
l'usage dans le BeanBox ou tout autre environnement de JavaBean.
};
La méthode de run () contient le corps du fil de TimerAgent. Elle se compose de deux parties
alternatives, une pour le rythmeur et une pour le temporisateur monocoup. Si une valeur
d'intervalle est placée, elle écrit une boucle de while (), où elle va Sleep() pour le nombre
spécifique de millisecondes, effectue l'action désirée, et puis des répétitions jusqu'à ce que la
méthode Stop () s'appelle. Si le membre d'intervalle égale 0, alors une alarme monocoup est
LY_SII __ 177 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
placée. Un objet de date est employé pour obtenir la date du jour et pour la chronométrer qui
est alors employée pour calculer le nombre de heures jusqu'à ce que le temporisateur
monocoup aille au loin. Le TimerAgent va Sleep () une fois et se réveille au temps désigné,
effectue l'action désirée et sort le fil.
La méthode ciaEventFired() montre simplement tous les événements qu'elle reçoit de l'autre
CIAgents. Nous pourrions facilement augmenter cette méthode pour permettre à d'autres
agents de commencer et arrêter des temporisateurs employant CIAgentEvents au lieu des
appels de méthode. Cependant, cette fonction n'est pas exigée dans l'application de
PCManager.
}
public void ciaEventFired(CIAgentEvent e) {
trace(name + “: CIAgentEvent received by ” + name + “ from ” +
e.getSource() + “ with arg ” + e.getArgObject()) ;
}
DataInputStream data =
new DataInputStream(process.getInputStream());
while ((line = data.readLine()) != null)
{
trace(line);
}
data.close();
Noter que le TimerAgent fournit un ensemble flexible de possibilités. Une alarme peut être
placée pour commencer des supports de système à minuit ou une alarme d'intervalle peut être
placée pour informer l'utilisateur chaque heure l'heure. Des alarmes peuvent également être
employées pour donner un coup de pied au loin l'autre CIAgents pour faire leur chose.
Encore, il n'y a pas beaucoup d'intelligence ici, mais c'est logiciel utile néanmoins.
Montres : Le FileAgent
Le prochain CIAgent est appelé FileAgent parce que son but dans la vie est d'observer un
système de fichiers et de faire l'application savoir quand un certain événement spécifique se
produit. L'agent peut alerter l'utilisateur avec l'AlertDialog toutes les fois qu'un dossier est
modifié, ou si la taille d'un dossier devient trop grande (surveillant la taille d'un fichier
SWAP, par exemple). Elle peut également alerter une application ou un agent différent toutes
les fois que le dossier de cible est supprimé. Comme le TimerAgent, le FileAgent peut
effectuer une de trois actions quand il détecte l'état de montre. Il peut montrer une alerte,
exécuter une commande ou commencer une application, ou informer un autre CIAgent de la
condition.
Une grande partie de la logique du FileAgent est semblable au TimerAgent, ainsi nous
discuterons seulement les membres uniques de données et () la méthode de processus. Trois
états de montre sont soutenus : si le dossier EST MODIFIÉ, si le dossier EST SUPPRIMÉ (il
n'existe pas dans le système de fichiers), et si le dossier dépasse une taille de seuil en bytes.
Le nom du dossier ou de l'annuaire est stocké dans le membre de corde de nom de fichier, et
des informations sur quand elles ont été changées sont stockées dans lastChanged.
La méthode de run () va dormir toutes les 15 secondes et examine l'état de dossier spécifique
chaque fois que elle se réveille. Si la condition de montre est remplie, alors l'action spécifique
est effectuée comme elle était dans le TimerAgent.
String fileName ;
File file ;
long lastChanged ;
int condition ;
int threshold ;
LY_SII __ 180 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Dialog actionDialog ;
String parms ;
Thread.sleep((long)interval) ; // in milliseconds
trace(name + “: checking ” + fileName + “ \n”) ;
}
catch (InterruptedException e)
{
// interrupted
}
boolean cond = checkCondition() ;
if (cond == true) {
performAction() ;
}
}
return ;
}
boolean checkCondition() {
boolean truth = false ;
switch (condition) {
case MODIFIED:
truth = changed() ;
break ;
case DELETED: // was file deleted?
truth = !exists() ; // see if file exists
break ;
case THRESHOLD:
truth = threhold > length() ;
break ;
}
return truth ;
}
void performAction() {
switch (action) {
case 0:
trace(name + “: Alert fired \n”) ;
((AlertDialog)actionDialog).label1.setText(parms) ;
actionDialog.show() ;
if (((AlertDialog)actionDialog).cancel == true) stop() ;
break ;
case 1:
trace(name + “: Executing command \n”) ;
executeCmd(parms) ;
break ;
case 2:
notifyCIAgentEventListeners(
new CIAgentEvent(this,“interval”)); // signal
break ;
}
}
Application de PCManager
//{{CONNECTION
// Create with title, show as modal...
AlarmDialog dlg = new AlarmDialog(this, “Create Alarm”, true);
//}}
dlg.show() ;
TimerAgent agent = dlg.getAgent() ;
if (agent != null) {
alarms.put(agent.name, agent) ;
list1.addItem(agent.getDisplayString()) ;
agent.textArea = textArea1 ;
agent.process() ;
LY_SII __ 183 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
}
}
//{{CONNECTION
// Create with title, show as modal...
WatchDialog dlg = new WatchDialog(this, “Create Watch”, true);
//}}
dlg.show() ;
FileAgent agent = dlg.getAgent() ;
if (agent != null) {
watches.put(agent.name, agent) ;
list1.addItem(agent.getDisplayString()) ;
agent.textArea = textArea1 ;
agent.process() ;
}
}
}
}
public PCManager() {
//{{INIT_CONTROLS
LY_SII __ 184 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
setLayout(null);
addNotify();
resize(insets().left + insets().right + 405,insets().top +
insets().bottom + 305);
openFileDialog1 = new java.awt.FileDialog(this,
“Open”,FileDialog.LOAD);
//$$ openFileDialog1.move(36,276);
list1 = new java.awt.List(0,false);
add(list1);
list1.reshape(insets().left + 12,insets().top + 24,372,70);
textArea1 = new java.awt.TextArea();
textArea1.reshape(insets().left + 12,insets().top + 144,374,135);
add(textArea1);
label1 = new java.awt.Label(“Activity Log”);
label1.reshape(insets().left + 12,insets().top + 120,196,20);
add(label1);
label2 = new java.awt.Label(“Watches/Alarms”);
label2.reshape(insets().left + 12,insets().top + 0,180,20);
add(label2);
setTitle(“CIAgent PCManager Application”);
//}}
//{{INIT_MENUS
mainMenuBar = new java.awt.MenuBar();
//{{DECLARE_CONTROLS
java.awt.FileDialog openFileDialog1;
java.awt.List list1;
java.awt.TextArea textArea1;
java.awt.Label label1;
java.awt.Label label2;
//}}
//{{DECLARE_MENUS
java.awt.MenuBar mainMenuBar;
java.awt.Menu menu1;
java.awt.Menu menu2;
java.awt.Menu menu4;
LY_SII __ 186 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
java.awt.Menu menu3;
//}}
La classe d'AlarmDialog
// Cancel
void button2_Clicked(Event event) {
//{{CONNECTION
// Hide the Dialog
hide();
//}}
}
// OK
void button1_Clicked(Event event) {
if (action == 1) agent.setDialog(new
ExecuteDialog((Frame)this.getPar-
ent(),name + “Execute”, false)) ;
//{{CONNECTION
// Hide the Dialog
hide();
//}}
}
super(parent, modal);
//{{INIT_CONTROLS
setLayout(null);
addNotify();
resize(insets().left + insets().right + 433,insets().top +
insets().bottom + 351);
setBackground(new Color(12632256));
label3 = new java.awt.Label(“Action”);
label3.reshape(insets().left + 48,insets().top + 228,84,36);
add(label3);
label4 = new java.awt.Label(“Parameters”);
label4.reshape(insets().left + 36,insets().top + 264,108,24);
add(label4);
textField1 = new java.awt.TextField();
textField1.reshape(insets().left + 156,insets().top +
264,187,29);
add(textField1);
label5 = new java.awt.Label(“Interval”);
label5.reshape(insets().left + 84,insets().top + 168,96,24);
add(label5);
choice2 = new java.awt.Choice();
choice2.addItem(“Alert”);
choice2.addItem(“Execute”);
choice2.addItem(“Fire CIAgent Event”);
add(choice2);
choice2.reshape(insets().left + 156,insets().top + 228,134,24);
label2 = new java.awt.Label(“Time”);
label2.reshape(insets().left + 84,insets().top + 108,89,24);
label2.setBackground(new Color(16777215));
add(label2);
Group1 = new CheckboxGroup();
radioButton1 = new java.awt.Checkbox(“One Time”, Group1, false);
radioButton1.reshape(insets().left + 24,insets().top +
48,147,17);
add(radioButton1);
radioButton2 = new java.awt.Checkbox(“Repeating”, Group1, false);
radioButton2.reshape(insets().left + 24,insets().top +
144,126,20);
add(radioButton2);
textField2 = new java.awt.TextField();
textField2.reshape(insets().left + 216,insets().top +
108,127,26);
add(textField2);
textField3 = new java.awt.TextField();
LY_SII __ 188 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
textField3.reshape(insets().left + 216,insets().top +
168,124,27);
add(textField3);
label6 = new java.awt.Label(“seconds”);
label6.reshape(insets().left + 348,insets().top + 168,84,26);
label6.setBackground(new Color(16777215));
add(label6);
button2 = new java.awt.Button(“Cancel”);
button2.reshape(insets().left + 252,insets().top + 312,84,24);
add(button2);
label7 = new java.awt.Label(“Name”);
label7.reshape(insets().left + 24,insets().top + 12,152,28);
add(label7);
textField4 = new java.awt.TextField();
textField4.reshape(insets().left + 180,insets().top + 12,134,26);
add(textField4);
button1 = new java.awt.Button(“OK”);
button1.reshape(insets().left + 108,insets().top + 312,84,24);
add(button1);
label8 = new java.awt.Label(“hh:mm”);
label8.reshape(insets().left + 348,insets().top + 108,78,24);
add(label8);
setTitle(“”);
setResizable(false);
//}}
textField4.setText(“Alarm”) ;
}
//{{DECLARE_CONTROLS
java.awt.Label label1;
LY_SII __ 189 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
java.awt.Choice choice1;
java.awt.Label label3;
java.awt.Label label4;
java.awt.TextField textField1;
java.awt.Label label5;
java.awt.Choice choice2;
java.awt.Label label2;
java.awt.Checkbox radioButton1;
CheckboxGroup Group1;
java.awt.Checkbox radioButton2;
java.awt.TextField textField2;
java.awt.TextField textField3;
java.awt.Label label6;
java.awt.Button button2;
java.awt.Label label7;
java.awt.TextField textField4;
java.awt.Button button1;
java.awt.Label label8;
//}}
La classe de WatchDialog
//{{CONNECTION
// Create with title, show as modal...
FileDialog dlg = new FileDialog((Frame)this.getParent(), “Select
File
or Directory”, FileDialog.LOAD);
//}}
dlg.show() ;
String dir = dlg.getDirectory() ;
String fName = dlg.getFile() ;
textField1.setText(dir+fName) ;
}
// cancel
void button3_Clicked(Event event) {
LY_SII __ 190 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
//{{CONNECTION
// Hide the Dialog
hide();
//}}
}
// OK
void button2_Clicked(Event event) {
super(parent, modal);
//{{INIT_CONTROLS
setLayout(null);
addNotify();
resize(insets().left + insets().right + 430,insets().top +
insets().bottom + 309);
setBackground(new Color(12632256));
label1 = new java.awt.Label(“File or Directory”);
label1.reshape(insets().left + 24,insets().top + 48,135,24);
add(label1);
label2 = new java.awt.Label(“Action”);
label2.reshape(insets().left + 24,insets().top + 180,144,33);
add(label2);
choice1 = new java.awt.Choice();
choice1.addItem(“Alert”);
choice1.addItem(“Execute”);
choice1.addItem(“Fire CIAgent Event”);
add(choice1);
choice1.reshape(insets().left + 36,insets().top + 216,146,28);
textField1 = new java.awt.TextField();
LY_SII __ 191 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
super.show();
}
LY_SII __ 192 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
//{{DECLARE_CONTROLS
java.awt.Label label1;
java.awt.Label label2;
java.awt.Choice choice1;
java.awt.TextField textField1;
java.awt.Label label3;
java.awt.Choice choice2;
java.awt.Label label4;
java.awt.TextField textField2;
java.awt.Button button1;
java.awt.Label label5;
java.awt.TextField textField3;
java.awt.Button button2;
java.awt.Button button3;
java.awt.Label label6;
java.awt.TextField textField4;
//}}
Discussion
Il y a d'autres approches que nous pourrions avoir employées pour fournir la fonction fournie
par l'application de PCManager. En ce chapitre, nous avons consciemment décidé d'adopter
l'approche la plus franche dans l'intérêt de la clarté de la présentation. Dans cette section nous
discutons certaines des solutions de rechange possibles.
Une méthode populaire pour créer ces types d'applications simples d'agent est d'employer si
puis des règles comme moteur. De cette perspective, le TimerAgent serait employé
seulement comme agent événement-produisant, et le FileAgent serait employé comme sondes
dans l'antécédent d'une règle. Toutes les fois que le TimerAgent a envoyé un CIAgentEvent
à l'application de PCManager, il appellerait un cycle d'inférence de chaînage avant, avec des
règles spécifiant les divers conditions d'alarme ou de montre. Les trois actions devraient être
LY_SII __ 193 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
définies en tant que méthodes effectrices dans le RuleBase. Quand les feux d'une règle, la
méthode effectrice s'appelleraient et l'AlertDialog, l'ExecuteDialog, ou un CIAgentEvent
serait exécuté.
Cette conception aurait certainement effectué notre interface utilisateurs. Au lieu de compléter
met en place dans l'AlarmDialog ou les panneaux de WatchDialog, l'utilisateur auraient
complété probablement si puis calibre de règle. Le PCManager serait alors un grand
RuleBase qui reçoit CIAgentEvents et effectue inferencing (et actions) en réponse à ces
événements. Nous nous servons de la fonction semblable dans l'application de marché
discutée en chapitre 10.
Résumé
En ce chapitre que nous avons développé une application simple de PCManager using deux
CIAgent-a basé les agents intelligents. Les questions principales incluent :
Exercices
Chapitre 9
Application du NewsFilter
L'Internet est le centre de l'application d'agent intelligent en ce chapitre. Une
application de base de lecteur Usenet d'Internet est conçue, mise en application,
et augmentée avec un agent intelligent qui aide un utilisateur en filtrant
l'information. L'utilisateur peut spécifier un profil des mots-clés et fournir la
rétroaction positive et négative sur chaque article de nouvelles. Trois autres
méthodes sont données pour filtrer les articles, y compris l'allumette de mot-clé,
le groupement, et la modélisation prédictive basée sur la rétroaction d'utilisateur.
Introduction
Le but de cette application est d'aider l'utilisateur à traiter tout les bruit électronique produit
dans les groupes de nouvelles. Ne serait-il pas grand si quand vous avez téléchargé un groupe
de nouvelles, tous que vous avez vus étaient les articles qui vous ont véritablement intéressé ?
Tous les poteaux de cette secousse sur la côte ouest disparaîtraient. Toutes les signalisations
de Spam offrant le grand service de téléphone mobile ou le plus grand logiciel puisque le pain
coupé en tranches perdrait jamais encore votre temps. D'une part, vous ne manqueriez jamais
un article ou un poteau de nouvelles qui ont discuté les matières qui vous intéressent. C'est la
motivation derrière le CIAgent NewsFilter. Dans le reste de ce chapitre nous nous montrons
comment appliquer les agents intelligents pour marquer et filtrer dehors les articles de
nouvelles non désirés. Nous explorerons également les mécanismes de base pour des groupes
de nouvelles d'Internet de lecture using le protocole de transport de nouvelles nettes.
Sous le menu déroulant de dossier décrit sur Figure9.2, l'utilisateur peut s'ouvrir et les
raccordements étroits avec le centre serveur choisi de nouvelles (un serveur courant le logiciel
de serveur de NNTP) et également ajouter le nom d'un groupe de nouvelles à la liste de
groupes de nouvelles. Pour charger réellement le groupe de nouvelles, l'utilisateur doit
double-click sur l'article dans l'awt de newsgroup.Liste. Différents articles peuvent être
LY_SII __ 196 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Le menu de profil représenté sur Figure9.3 contient une liste d'actions liées à l'entretien du
profil de NewsFilter de l'utilisateur. L'option de mots-clés… montre un dialogue secondaire
qui permet à l'utilisateur d'écrire une liste de mots ou les limites qui est d'intérêt. Le dialogue
de mot-clé permet à l'utilisateur d'ajouter ou enlever des mots-clés de la liste. La spécification
des mots-clés est la première chose qu'un utilisateur devrait faire en commençant à établir un
profil d'utilisateur adapté aux besoins du client. Un ensemble de défaut de limites est fourni
dans l'application de NewsFilter. Les dix mots-clés de défaut sont : {« Java, » « agents, »
« brouillé, » « intelligent, » « neural, » « réseau, » « génétique, » « Symantec, » « café, »
« haricots »}.
Chaque article est recherché et le nombre de fois où chaque mot-clé apparaît est compté et
additionné. Ce nombre total de coups de mot-clé est employé comme points crus d'allumette
pour le filtrage de mot-clé.
L'option de profil de création détruira le profil courant et créera un neuf, using les mots-clés
décrits dans le dialogue de mot-clé. Le profil de filtre se compose de deux dossiers des textes.
Le premier, newsfilter.prf, contient la définition d'ensemble de données (comme décrit dans
chapitre 5), qui est une liste de types de données, continus ou discrets, et les noms de champ
correspondants. Ce dossier décrit la disposition des données dans le dossier de newsfilter.dat.
L'utilisateur peut ajouter des disques au dossier de newsfilter.dat en choisissant l'article
d'ajouter ou ajouter tout l'article de menu d'articles. Ajouter l'article apposera un disque
simple contenant les comptes d'allumette, la valeur courante de rétroaction, et les points
courants de filtre à newsfilter.dat. Ajouter tous les articles apposera les disques de profil
pour tous les articles dans le groupe actuellement chargé de nouvelles au dossier de
newsfilter.dat. Ce dossier est employé comme ensemble de données d'entrée pour construire le
filtre neural de faisceau et le filtre neural de rétroaction.
L'article de points et marquent tous les articles appliquera le filtre actuellement choisi
(mot-clé, faisceau, ou rétroaction) à l'article spécifique ou articles et mettra à jour leurs
points d'allumette. Pour le filtre de mot-clé, les points sont simplement la somme de toutes les
allumettes de mot-clé comme décrit plus tôt. Pour le filtre de faisceau, ces points sont la
moyenne des points de mot-clé pour tous les articles qui tombent dans ce faisceau (voir le
chapitre 5 pour l'examen complet du groupement neural). Les points pour le filtre de
rétroaction sont l'activation arrière d'unité de rendement de réseau neurologique de
propagation, une valeur s'étendant de 0.0 à 1.0. Nous discuterons ceci en plus détail dans la
prochaine section.
Le menu de filtre contient les options liées à si le filtrage est appliqué aux articles dans les
groupes de nouvelles, que le type de filtre est employé, et bâtiment que les modèles ont exigé
LY_SII __ 197 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
pour les diverses méthodes de filtre. Filtrer les articles, suivant les indications du schéma
9.4, est un article de menu de checkbox qui se transfère sur au loin. Quand vérifiés, les articles
seront filtrés using la technique indiquée dans le prochain groupement de menu. Le défaut
emploie des mots-clés, mais l'utilisateur peut choisir using des faisceaux ou rétroaction
d'utilisation comme méthode de filtre à appliquer.
Le prochain ensemble d'options de menu est employé pour établir les modèles internes exigés.
Construire le filtre de mot-clé force simplement un compte de toutes les allumettes de mot-
clé dans les articles chargés. Le filtre de faisceau de construction instancie un réseau
neurologique de carte de Kohonen et indique les données dans le dossier de newsfilter.dat
pour former le réseau. Construire le filtre de rétroaction crée et forme un réseau
neurologique de propagation arrière qui emploie les données de rétroaction dans le dossier de
newsfilter.dat comme cible d'un modèle de prévision.
Le menu de rétroaction montré sur Figure9.5 permet à l'utilisateur d'assigner une valeur
correspondant à l'utilité de l'article. Chaque article a une valeur de rétroaction qui est
automatiquement placée quand le groupe de nouvelles est lu. Cette valeur s'étend de 0 pour
des articles où il n'y a aucune allumette à un 1 pour les articles qui ont plus de 5 allumettes.
Cette tâche automatique est fournie comme convenance à l'utilisateur de sorte qu'une valeur
ne doive pas être placée pour chaque article.
Un exemple
Dans cette section, nous décrivons le processus employé pour créer et utiliser les trois filtres
fournis par l'application de NewsFilter. Pour commencer l'application, courir la commande
suivante :
Java NewsFilter
Quand le panneau principal de NewsFilter est montré, aller d'abord classer et choisir les
nouvelles ouvertes accueillir… l'option. Le dialogue de NewsHost est montré montrant un
serveur de nouvelles de défaut. Les utilisateurs devraient écrire le nom de leur serveur de
nouvelles de Service Provider d'Internet ici. Si CORRECT est cliqué, un message sera
évident dans le TextArea déclarant que le NewsFilter essaye de se relier au serveur. La
réponse du serveur sera faite écho au TextArea.
Après, aller au menu de profil, et choisir les mots-clés. Une liste des 10 mots-clés de défaut
hardcoded dans l'application de NewsFilter est montrée. Les utilisateurs peuvent choisir
n'importe quel mot-clé qu'ils souhaitent (des mots simples seulement, aucunes expressions).
Après, choisi créer le profil du même menu. Ceci initialise les deux fichiers des profils,
LY_SII __ 198 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
newsfilter.dat et newsfilter.dfn. Vous êtes prêt à commencer à vous construire profil personnel
de filtre.
La liste de newsgroup sur le gauche supérieur s'amorce avec cinq groupes de nouvelles
d'Internet de défaut. Ils sont : comp.ai.fuzzy, comp.ai.neural-nets, comp.lang.java.api,
comp.lang.java.misc, et comp.lang.java.tech. Ces groupes de nouvelles ont été choisis parce
qu'ils sont les endroits raisonnables pour trouver des poteaux ou des articles de nouvelles
contenant notre liste de mot-clé de défaut. Pour charger le premier groupe de nouvelles,
comp.lang.ai, double-click sur cet article dans la liste. Le NewsFilter commence alors à
demander tous les articles que le centre serveur de nouvelles a dans le groupe de nouvelles.
Pendant que chaque article est téléchargé, la ligne objet est analysée de l'en-tête et est montrée
dans les articles de nouvelles énumèrent sur la droite supérieure, et le corps ou le texte du
message est lu et montré dans le TextArea. La ligne objet et le corps sont stockés dans l'objet
de NewsArticle.
Maintenant qu'un ensemble d'articles de nouvelles est chargé, nous pouvons voir qu'à quel
point ils assortissent nos mots-clés spécifiques. Les points d'allumette pour l'ensemble de
totalité peuvent être calculés using le profil/points tous les articles ou, pour un article
individuel, using l'article de profil/points. L'allumette de mot-clé est montrée au fond du
TextArea. Filtrer les articles en allant au menu de filtre et en vérifiant l'article de menu
d'articles de filtre au dessus de ce menu. Les articles sont assortis par leurs points d'allumette
et affiché à nouveau dans l'ordre décroissant dans les articles de nouvelles énumérer. L'article
de marquage supérieur est choisi, et le corps de cet article est montré dans le TextArea.
Quand l'article de menu d'articles de filtre est ne pas sélectionner, la liste d'article retourne à
l'ordre original.
Afin d'utiliser le filtre de faisceau ou le filtre de rétroaction, des données de profil doivent
d'abord être sauvées sur un ensemble d'articles raisonnablement classé. Par défaut, le
NewsFilter lit seulement 20 articles de chaque groupe de nouvelles (c'est une constante qui
peut être facilement changée dans le code). Si les cinq groupes de nouvelles de défaut sont
lus, cela donne 100 disques de profil d'article. Pour stocker les profils d'article au dossier des
textes de newsfilter.dat, choisir l'ajouter toute l'option de menu d'articles dans le menu de
profil. Supposant que le serveur de nouvelles a eu 20 articles dans le groupe de nouvelles de
comp.lang.ai, 20 disques seraient écrits.
Maintenant qu'il y a des données de profil, nous pouvons utiliser le filtre de faisceau. D'abord,
choisir l'option de filtre de faisceau de construction sur le menu de filtre. On crée un réseau
neurologique qui lit le dossier de newsfilter.dat et groupe les disques de profil d'article dans 4
segments. (C'était une décision arbitraire, il pourrait facilement avoir été 9, 16, ou 25). Les
points crus d'allumette pour chaque article dans chaque faisceau sont additionnés et une
moyenne est calculée. Les points pour chaque article sont placés à la valeur moyenne du
faisceau qu'elle est tombé dans. Cette étape produit le modèle de segmentation employé par le
filtre de faisceau. Cependant, afin d'utiliser le filtre de faisceau, elle doit également être
choisie en tant qu'à filtre sur le menu de filtre. Si des articles de filtre est vérifiés, la liste
LY_SII __ 199 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Le dernier filtre fourni dans l'application de NewsFilter est le filtre de rétroaction. Ceci
emploie aussi un modèle de réseau neurologique pour déterminer les points d'article. Un
modèle de régression arrière de propagation est créé using les disques de profil d'article
comme entrée et les points de rétroaction comme valeur de rendement de cible. Si aucun des
arrangements de rétroaction de défaut n'était dépassé avant que les articles aient été ajoutés au
profil, le modèle prévoira des points s'étendant de 0 à 1, où tous les articles ayant plus de 5
allumettes de mot-clé sont un 1. Si différentes valeurs étaient données pour les articles choisis
par rétroaction d'utilisateur explicite using les cinq niveaux définis dans le menu de
rétroaction, les résultats pourraient être légèrement différents. Par exemple, si des articles qui
ont contenu le mot « neural » étaient évalués comme plus intéressants que ceux qui a contenu
« Java, » ils auraient de plus hauts points du filtre de rétroaction, quoique chacun ait eu des
points crus identiques d'allumette.
Après que le modèle de filtre de rétroaction soit établi, il doit être choisi comme technique
désirée de filtre en vérifiant l'option de utilisation de rétroaction sur le menu de filtre. Si des
articles de filtre est allumés, les articles dans la boîte de liste de droite supérieure seront
commandés à nouveau selon les points qu'ils ont obtenus du modèle neural de prévision.
Classe de NewsFilter
La classe de NewsFilter est la classe d'application principale dans cette application. Elle
prolonge la vue using deux commandes de liste et un grand TextArea comme éléments
principaux d'interface, et un MenuBar des options pour permettre à l'utilisateur d'effectuer les
actions désirées. Une grande partie du code de GUI est produit par le produit visuel de
Symantec Café, et ainsi nous parlerons seulement de lui à un à niveau élevé.
Des actions qui traitent des données de communication et de lecture du serveur de nouvelles
sont manipulées par la classe de NewsFilter. Les actions se sont rapportées à établir le profil
d'utilisateur, articles de marquage, ou construisant les filtres de réseau neurologique sont
manipulés par le FilterAgent. La plupart de ces appels de méthodes sont traitées
synchroniquement. C'est-à-dire, l'application de NewsFilter appelle le FilterAgent dans son
fil de traitement principal et la commande ne retourne pas jusqu'à ce que la méthode de
FilterAgent accomplisse. Les exceptions à ce modèle sont les méthodes de
BuildClusterFilter_Action () et de BuildFeedbackFilter_Action (). Ils appellent les méthodes
dans le FilterAgent qui allument simplement les commutateurs ou les drapeaux booléens
pour que l'agent voie quand il se réveille périodiquement recherchant le travail. Cette
approche est employée parce que la formation des réseaux neurologiques peut être une action
LY_SII __ 200 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
longue et en gérant ces tâches asynchrone, l'application de NewsFilter n'est pas attachée vers
le haut d'attendre ces derniers pour accomplir. Le FilterAgent signale quand il est fait en
appelant le clusterNetBuilt () et des méthodes de scoreNetBuilt (). Ceux-ci permettent les
options correspondantes de menu de filtre, de sorte que le filtrage de faisceau et de
rétroaction puisse être choisi.
//{{CONNECTION
// Create with title, show as modal...
NewsGroupDialog dlg = new NewsGroupDialog(this,
“Enter name of New Group to add to list”, true);
dlg.show();
//}}
String newsGroup = dlg.textField1.getText() ;
if (newsGroup != null) {
list1.addItem(newsGroup) ;
}
}
//{{CONNECTION
// Create with title, show as modal...
NewsHostDialog dlg = new NewsHostDialog(this,
“Enter address or name of News Server”, true) ;
//}}
dlg.setNewsHost(newsHost) ; // set to current value
dlg.show() ;
String temp = dlg.newsHost ;
if (temp != null) {
newsHost = temp ;
}
if (newsHost != null) {
textArea1.appendText(“\nConnecting to ” + newsHost + “ \n” );
connectToNewsHost() ;
}
}
//{{CONNECTION
// Create with title, show as modal...
KeywordDialog dlg =
new KeywordDialog(this,“Specify Filter Keywords”,true);
//}}
dlg.setKeywords(keywords) ; // initialize the list
dlg.show() ;
keywords = dlg.getKeywords();
if (keywords != null) {
textArea1.appendText(keywords[0]) ;
}
}
// user selected a news group -- download it
void NewsGroup_Action(Event event) {
list2.clear() ;
textArea1.setText(“”) ;
articles = new Vector() ;
LY_SII __ 201 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
break ;
case 1: // cluster
keywordFilter.setState(false) ;
clusterFilter.setState(true) ;
feedbackFilter.setState(false) ;
break ;
case 2: // feedback
keywordFilter.setState(false) ;
clusterFilter.setState(false) ;
feedbackFilter.setState(true) ;
break ;
}
filterType = fType ;
if (filterArt.getState() == true) filterArticles() ;
}
void clusterNetBuilt() {
clusterFilter.enable() ; // FilterAgent has completed
}
void scoreNetBuilt() {
feedbackFilter.enable() ; // FilterAgent has completed
}
articles.addElement(art) ;
}
}
void SaveArticle_Action(Event event) {
//{{CONNECTION
// Action from Save... Show the SaveFileDialog
saveFileDialog1.show();
//}}
String fileName = saveFileDialog1.getFile();
if (fileName != null) {
int index = list2.getSelectedIndex();
if (index != -1) {
NewsArticle art = (NewsArticle)articles.elementAt(index) ;
art.writeArticle(fileName) ;
}
}
}
public NewsFilter() {
//{{INIT_CONTROLS
setLayout(null);
addNotify();
resize(insets().left + insets().right + 587,insets().top +
insets().bottom + 404);
setBackground(new Color(16777215));
openFileDialog1 =
new java.awt.FileDialog(this, “Open”,FileDialog.LOAD);
saveFileDialog1 =
new java.awt.FileDialog(this, “Save”,FileDialog.SAVE);
//$$ openFileDialog1.move(36,336);
list1 = new java.awt.List(0,false);
add(list1);
list1.reshape(insets().left + 12,insets().top + 36,276,88);
list1.setBackground(new Color(16777215));
list2 = new java.awt.List(0,false);
add(list2);
list2.reshape(insets().left + 300,insets().top + 36,276,88);
list2.setBackground(new Color(16777215));
textArea1 = new java.awt.TextArea();
textArea1.reshape(insets().left + 12,insets().top + 144,564,208);
add(textArea1);
label1 = new java.awt.Label(“Newsgroup”);
label1.reshape(insets().left + 12,insets().top + 12,93,24);
LY_SII __ 204 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
add(label1);
label2 = new java.awt.Label(“News Item”);
label2.reshape(insets().left + 300,insets().top + 12,86,24);
add(label2);
setTitle(“CIAgent News Filter Application”);
setResizable(false);
//}}
//{{INIT_MENUS
mainMenuBar = new java.awt.MenuBar();
menu4.addSeparator();
menu4.add(“Build Keyword filter”);
menu4.add(“Build Cluster filter”);
menu4.add(“Build Feedback filter”);
mainMenuBar.add(menu4);
}
return super.handleEvent(event);
}
if (label.equalsIgnoreCase(“Save article...”)) {
SaveArticle_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“Load article...”)) {
LoadArticle_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“Add article”)) {
AddArticle_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“Add all articles”)) {
AddAllArticles_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“Score article”)) {
ScoreArticle_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“Score all articles”)) {
ScoreAllArticles_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“About”)) {
About_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“Exit”)) {
Exit_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“Keywords...”)) {
LY_SII __ 207 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Keywords_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“Create profile”)) {
CreateProfile_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“Useless”)) {
Feedback_Action(0);
return true;
} else
if (label.equalsIgnoreCase(“Not very useful”)) {
Feedback_Action(0.25);
return true;
} else
if (label.equalsIgnoreCase(“Neutral”)) {
Feedback_Action(0.5);
return true;
} else
if (label.equalsIgnoreCase(“Mildly interesting”)) {
Feedback_Action(0.75);
return true;
} else
if (label.equalsIgnoreCase(“Interesting”)) {
Feedback_Action(1.0);
return true;
} else
if (label.equalsIgnoreCase(“Filter articles”)) {
FilterArticles_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“using Keywords”)) {
FilterType_Action(0);
return true;
} else if (label.equalsIgnoreCase(“using Clusters”)) {
FilterType_Action(1);
return true;
} else if (label.equalsIgnoreCase(“using Feedback”)) {
FilterType_Action(2);
return true;
} else
if (label.equalsIgnoreCase(“Build Keyword filter”)) {
BuildKeywordFilter_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“Build Cluster filter”)) {
BuildClusterFilter_Action(event);
return true;
} else
if (label.equalsIgnoreCase(“Build Feedback filter”)) {
BuildFeedbackFilter_Action(event);
return true;
}
}
if (event.target instanceof List) {
if (event.target == list1) {
// load selected news group
LY_SII __ 208 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
NewsGroup_Action(event) ;
return true;
}
if (event.target == list2) {
// load selected article
NewsItem_Action(event);
return true ;
}
}
return super.action(event, arg);
}
//{{DECLARE_CONTROLS
java.awt.FileDialog openFileDialog1;
java.awt.FileDialog saveFileDialog1;
java.awt.List list1;
java.awt.List list2;
java.awt.TextArea textArea1;
java.awt.Label label1;
java.awt.Label label2;
//}}
//{{DECLARE_MENUS
java.awt.MenuBar mainMenuBar;
java.awt.Menu menu1;
java.awt.Menu menu6;
java.awt.Menu menu2;
java.awt.Menu menu4;
java.awt.CheckboxMenuItem filterArt;
java.awt.CheckboxMenuItem keywordFilter;
java.awt.CheckboxMenuItem clusterFilter;
java.awt.CheckboxMenuItem feedbackFilter;
java.awt.Menu menu5;
java.awt.Menu menu3;
//}}
Les membres des données de la classe de NewsFilter incluent le newsHost, qui se transfère
sur le serveur global des informations d'IBM, la douille de nouvelles, qui est utilisée pour se
relier et parler au serveur de nouvelles, et les jets de newsIn et de newsOut, qui sont employés
pour envoyer des données au-dessus du raccordement de douille. Deux vecteurs, articles et
originalArticleList, tiennent la liste non triée assortie et originale d'articles actuellement
chargés dans l'application de NewsFilter. Le membre de currentArt est une référence à
l'exemple de NewsArticle choisi dans la boîte de liste de droite supérieure. La rangée de
corde de mots-clés tient les mots que l'utilisateur a définis pour l'usage en évaluant la
pertinence des articles.
faisceau, et le filtre de rétroaction de 2 moyens. Ces valeurs sont placées dans la méthode de
FilterType_Action () basée sur les arrangements des trois CheckboxMenuItems
correspondant dans le menu de filtre.
try {
news = new Socket(newsHost, 119) ;
newsIn = new DataInputStream(news.getInputStream()) ;
newsOut = new PrintStream(news.getOutputStream()) ;
String reply = newsIn.readLine();
textArea1.appendText( reply + “\n”) ;
}
catch (Exception e) {
textArea1.appendText(“Exception:” + e) ;
}
}
try {
String cmd = “QUIT \n” ;
newsOut.println(cmd) ;
textArea1.appendText( cmd + “ \n” ) ;
newsIn.close() ;
LY_SII __ 210 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
}
catch (Exception e) {
textArea1.appendText(“Exception:” + e) ;
}
Faire une boucle les sorties quand la limite de maxArticles est atteinte, ou si un code retour
d'erreur est reçu du serveur. Le cas échéant des articles sont lus, le premier est choisi dans la
liste de nouvelle, et son corps est montré dans le TextArea. Avant que le filtrage soit effectué
sur le nouveau groupe, l'ensemble original d'articles dans l'ordre original est copié au membre
d'originalArticles. Si le filtrage est tourné sur les articles sont immédiatement filtrés using l'à
filtre spécifique.
LY_SII __ 211 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Noter svp, la classe de NewsFilter n'est pas un lecteur Usenet commercial. Il y a d'une
logique beaucoup plus de contrôle d'erreurs qui devrait être ajoutée pour un lecteur Usenet
d'usage universel. Cependant, ceci fournit le mécanisme de base pour passer en revue un
groupe de nouvelles d'Internet et nous permet d'obtenir des articles de nouvelles pour établir
le profil d'utilisateur.
int maxArticles = 20 ;
boolean exit = false ;
try {
String cmd = “GROUP ” + newsGroup + “ \n” ;
newsOut.println(cmd) ;
String reply = newsIn.readLine();
textArea1.appendText( cmd + “ \n” + reply + “\n”) ;
String retCode ;
do {
textArea1.setText(“”);
cmd = “HEAD \n” ;
newsOut.println(cmd) ;
reply = newsIn.readLine();
textArea1.appendText( cmd + “ \n” + reply + “\n”) ;
StringTokenizer tok = new StringTokenizer(reply, “ ”) ;
retCode = tok.nextToken() ;
String id = tok.nextToken() ;
String msgId = tok.nextToken() ;
if (!retCode.equals(“221”)) continue ;
// now read all header records for this article and parse
NewsArticle art = parseHeader(id) ;
list2.addItem( art.subject ) ; // display subject only
articles.addElement(art) ; // add to Vector
} while(!reply.equals(“.”)) ;
art.body = textArea1.getText() ;
cmd = “\n NEXT \n” ;
newsOut.println(cmd) ;
reply = newsIn.readLine();
textArea1.appendText( cmd + “ \n” + reply + “\n”) ;
StringTokenizer st2 = new StringTokenizer(reply) ;
retCode = st2.nextToken() ; // response code
}La méthode de filterArticles () vérifie d'abord pour voir si les articles CheckboxMenuItem
de filtre dans le menu de filtre est choisis. Si tous les articles dans le groupe de nouvelles
n'ont pas été marqués encore, ils sont marqués. Noter que les articles, l'ensemble courant de
mots-clés, et tous le type courant de filtre sont passés au FilterAgent pour le marquage. Le
résultat de cet appel est que le membre de points de chaque NewsArticle est placé à la valeur
appropriée basée sur le courant à filtre. La méthode d'insertionSort () s'appelle pour assortir
les articles par ordre décroissant par des points. La liste d'article est alors dégagée et remplie
avec les articles dans le nouvel ordre.
Cette méthode d'insertionSort () est une exécution standard de l'algorithme de sorte d'insertion
(Sedgewick 1984) adapté pour Java. D'abord, les éléments dans le vecteur sont copiés dans
une rangée pour la convenance. Après, commençant au deuxième élément dans la rangée,
nous marchons par la rangée, assortissant pendant que nous allons. Une fois que l'algorithme
de sorte est complet, les éléments de tableau sont copiés de nouveau dans un vecteur de
retour.
int i, j ;
int size = articles.size() ;
Classe de NewsArticle
La classe de NewsArticle définit toutes les informations sur un article de nouvelles simple.
L'information primaire est l'identification de NNTP, qui est retournée par le serveur de
nouvelles en réponse à la « PROCHAINE » commande comme tous les articles dans le
groupe de nouvelles est lue. Le membre soumis contient la ligne objet analysée hors de
l'information d'en-tête. Le membre de corps est le texte entier retourné par le serveur en
réponse à la commande de « CORPS ». Le reste des membres sont employés par les fonctions
de NewsFilter. La rangée de comptes tient les points crus d'allumette de mot-clé. La somme
est la somme de comptes. La rétroaction est employée pour décrire l'utilité de l'article à
l'utilisateur (0.0 est inutile, 1.0 est intéressant). Les points sont le rang de l'article basé sur le
LY_SII __ 214 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
type de filtre étant appliqué. Le clusterId tient le segment dans lequel cet article tombe dans le
filtre de faisceau.
out.close() ;
}
catch (IOException e) {
System.out.println(“Error: couldn’t write news article to ”+
fileName + “\n”);
}
}
return outString.toString() ;
}
}
Classe de FilterAgent
La classe de FilterAgent est une sous-classe de CIAgent. Elle fournit toutes les fonctions
liées à la gestion des données de profil d'utilisateur, du mot-clé marquant, et de la construction
des modèles de réseau neurologique utilisés pour les filtres de faisceau et de rétroaction. La
classe de FilterAgent est étroitement accouplée à l'application de NewsFilter. En soi, elle
pourrait être employée simplement comme classe intelligente d'aide, avec toutes ses méthodes
simplement appelées directement par le NewsFilter. Cependant, pour illustrer comment un
agent intelligent peut être étroitement accouplé mais court toujours de façon autonome, nous
ajoutons un protocole de signalisation simple pour application de NewsFilter aux fonctions
longues initiées de FilterAgent.
NewsFilter newsFilter ;
protected KMapNet clusterNet ;
protected BackProp scoreNet ;
protected boolean buildClusterNet = false;
protected boolean buildScoreNet = false ;
if (arg.equals(“buildClusterNet”)) {
buildClusterNet = true ;
} else if (arg.equals(“buildScoreNet”))
buildScoreNet = true ;
}
Une approche semblable est adoptée quand le filtrage de rétroaction est permis et le modèle
arrière de propagation a été établi. Mais dans le cas de rétroaction, le rendement de réseau
neurologique est les points de rétroaction. Ainsi il est immédiatement assigné à l'article.score.
Une dernière fonction remplie dans cette méthode est l'attribution automatique des valeurs de
rétroaction. Une échelle simple de seuil détermine cette valeur basée sur les points crus
d'allumette. Si des valeurs user-specific étaient placées avant que des points () se soient
appelés, cette information serait perdue.
Comme indiqué par son nom, les computeClusterAverages () marche par le NewsArticles et
calcule la somme crue de points d'allumette et le nombre d'articles dans chaque faisceau. Les
points moyens d'allumette pour chaque faisceau sont calculés en divisant la somme par le
nombre d'articles dans le faisceau. Une fois que ces points moyens sont calculés, un autre
passage au-dessus du NewsArticles est exigé pour placer les points d'article à la valeur
moyenne correspondante.
try {
String id ;
trace(“”) ;
NewsArticle article = (NewsArticle)enum.nextElement() ;
score(article, keywords, filterType) ;
}
}
catch (Exception e) {
trace(“Exception:” + e) ;
}
if (filterType == 1) computeClusterAverages(articles) ;
}
enum = articles.elements() ;
while (enum.hasMoreElements()) {
NewsArticle article = (NewsArticle)enum.nextElement() ;
article.score = avgs[article.clusterId] ;
}
Le texte est recherché un mot à la fois, using un StringTokenizer pour faire l'analyse. La
longueur de chaque mot est employée pour limiter la recherche aux mots-clés de la même
longueur. Une recherche linéaire est exécutée en ce moment. Quand une allumette ne
distinguant pas majuscules et minuscules est trouvée, le keyHash est employé pour trouver
l'index du mot-clé. Cet index est employé pour incrémenter l'élément correspondant dans la
rangée de comptes []. Le résultat des countMultWordKeys est un choix de nombres entiers, où
chaque élément représente tout le nombre de coups pour chaque mot-clé dans le texte.
while (tok.hasMoreTokens()) {
String token = tok.nextToken() ;
int len = token.length();
if ((len < 50) && (table[len] != null)) {
Vector searchList = table[len] ;
Enumeration enum = searchList.elements() ;
while (enum.hasMoreElements()) {
String key = (String)enum.nextElement() ;
if (token.equalsIgnoreCase(key)) {
Integer index = (Integer)keyHash.get(key);
counts[index.intValue()]++ ; // found another one
continue ;
}
}
}
}
return counts ;
}
neurologiques de formation ou les arbres de décision. Le dossier contient des paires de types
de données et de noms de champ. Chaque mot-clé a une entrée pour le nombre de fois où il
apparaît dans le texte d'article. La valeur de rétroaction d'article et les points courants sont
également écrits. Noter que cette opération dépend de quel filtre est en vigueur, parce que les
points d'article varieront, basé sur le choix de filtre.
try {
FileWriter writer = new FileWriter(“newsfilter.dfn”) ;
BufferedWriter out = new BufferedWriter(writer) ;
for (int i=0 ; i < keywords.length ; i++) {
out.write(“continuous ”) ;
out.write(keywords[i]) ;
out.newLine() ;
}
out.write(“continuous ClassField”) ; // feedback
out.newLine() ;
out.write(“continuous score”) ;
out.newLine() ;
out.flush() ;
out.close() ;
}
catch (IOException e) {
System.out.println(“Error: couldn’t create ‘newsfilter.dfn’ \n”);
}
}
try {
FileWriter writer = new FileWriter(“newsfilter.dat”, true) ;
BufferedWriter out = new BufferedWriter(writer) ;
out.write(currentArt.getProfileString()) ;
out.newLine() ;
out.flush() ; out.close() ;
}
catch (IOException e) {
System.out.println(“Error: couldn’t append article to profile \n”);
}
}
void addAllArticlesToProfile(Vector articles) {
try {
FileWriter writer = new FileWriter(“newsfilter.dat”, true) ;
BufferedWriter out = new BufferedWriter(writer) ;
}
out.flush() ;
out.close() ;
}
catch (IOException e) {
System.out.println(“Error: couldn’t append article to profile \n”);
}
void trainClusterNet() {
clusterNet.cluster() ; // test
// clusterNet.display_network() ;
}
LY_SII __ 223 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
void trainScoreNet() {
DataSet dataSet = new DataSet(“ProfileData”, “newsfilter”) ;
dataSet.setDisplay(textArea) ;
dataSet.loadDataFile() ; // load the data set
Discussion
Peut-être le thème principal dans cette application est le rapport entre le code d'application et
l'agent intelligent. On pourrait facilement imaginer une exécution où le FilterAgent n'a pas
existé, et ses fonctions ont été remplies par la classe de NewsFilter elle-même. Cependant, en
maintenant la nature distincte des fonctions de FilterAgent, nous sommes en mesure pour la
LY_SII __ 224 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
réutiliser dans un agent composé ou un système multiagent. Tandis que le FilterAgent n'est
pas aussi autonome que le TimerAgents ou le FileAgents, il forme asynchrone les modèles
de réseau neurologique. Avec juste le travail additionnel, le FilterAgent CIAgent-basé a pu
être modifié pour établir des modèles de réseau neurologique contre n'importe quel ensemble
de données, plutôt que les données hardcoded de newsfilter.
Dans cette application, nous avons développé des possibilités modestes d'exploitation de
données (Bigus 1996). En fournissant l'autre CIAgents qui peut accéder à des bases de
données ou d'autres points d'émission (la classe de NewsFilter fournit des sources de
nouvelles d'Internet), un système autonome d'exploitation de données pourrait être établi. Le
TimerAgent et le FileAgent développés en chapitre 8 pourraient être employés à
automatiquement extraient des données aux temps d'ensemble ou seulement quand des
dossiers spécifiques sont modifiés.
Une autre issue de conception pour cette application est la manière que l'assortiment de mot-
clé est fait. Dans la classe de NewsFilter, seulement des allumettes complètes de mot-clé ont
été comptées. Il y a des algorithmes pour faire les allumettes partielles de sorte que le
singulier et le pluriel soient comptés pour chaque limite. L'approche simple d'entier-mot a
employé manque ici également des cas où les signes de ponctuation sont à côté du mot dans le
texte. Évidemment, plus l'information d'allumette est meilleure, plus nous pouvons filtrer les
articles pour l'utilisateur plus exactement.
La dernière issue est la compilation des données de profil d'utilisateur. Le filtre de faisceau et
le filtre de rétroaction exécuteront seulement comme les données de profil employées pour
former le réseau neurologique fondamental modèle. Avec plusieurs des nouveaux groupes
nous avons examiné, seulement quelques uns des 20 articles ont eu les allumettes crues plus
considérablement que 0 de mot-clé. Une solution à ce problème est de produire d'uns les
disques en boîte de profil, qui sont main construite avec un nombre représentatif d'allumettes
de mot-clé et de valeurs de rétroaction. Cet ensemble de formation pourrait être employé
comme données basses, et des profils choisis d'article pourraient être ajoutés.
Résumé
En ce chapitre, nous avons développé un filtre de l'information pour des groupes de nouvelles
d'Internet using un agent intelligent CIAgent-basé étroitement accouplé. Les questions
principales incluent :
Exercices
Chapitre 10
Application du MarketPlace
Ce chapitre se concentre sur les questions impliquées quand les agents
autonomes multiples agissent l'un sur l'autre dans les systèmes multiagent.
L'application est un marché d'agent intelligent, où les agents d'acheteur et de
vendeur coopèrent et concurrencent à traiter des transactions de ventes pour
leurs propriétaires. Un agent de facilitant est développé pour agir en tant que
directeur pour le marché. Les agents d'acheteur et de vendeur s'étendent
d'employer la logique hardcoded à inferencing basé sur les règles dans leurs
stratégies de négociation.
Introduction
Le FacilitatorAgent est l'intermédiaire ou le marieur entre les acheteurs et les vendeurs. Tous
les agents doivent s'inscrire au facilitant avant qu'ils puissent avoir toutes les interactions avec
d'autres agents dans le marché. Les vendeurs annoncent leur désir de vendre des produits ou
des services avec le FacilitatorAgent, alors que les acheteurs demandent au facilitant de
recommander un vendeur éventuel. Une fois que les agents d'acheteur et de vendeur ont été
présentés par le facilitant, ils communiquent toujours indirectement par le FacilitatorAgent.
Le schéma 10.1 montre le panneau principal de l'application de marché de CIAgent. Les deux
commandes de TextArea sont employées pour afficher des messages du facilitant et le
BuyerAgents et le SellerAgents dans le marché. Les options de MenuBar incluent le début
et l'arrêt, un choix contenu de détail ou de résumé de message, et le choix de trois types des
acheteurs et de vendeurs pour placer dans le marché. Ces agents peuvent être choisis dans
n'importe quelle combinaison des acheteurs et des vendeurs de base, intermédiaires, et
avancés. L'arrangement de défaut est pour qu'un BuyerAgent de base simple et un
SellerAgent de base soit dans le marché. Jusqu'à six indépendants et agents autonomes
peuvent être placés dans le marché en même temps.
Quand l'utilisateur choisit deux à six agents et choisit l'option de début à partir du menu
d'actions, un FacilitatorAgent simple est créé avec les agents choisis d'acheteur et de
LY_SII __ 227 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
vendeur. Le SellerAgents annoncent les articles qu'ils doivent se vendre en envoyant des
messages au facilitant et initialiser leur inventaire interne des articles. Le BuyerAgents
initialisent leurs propres listes d'achats. En ce moment, le marché est ouvert pour des affaires.
Tous les agents courent leurs propres fils qui se réveillent à intervalles spécifiques. La
première négociation de ventes a lieu quand une du BuyerAgents réveille et prend un article
de son wishList. Elle demande alors au facilitant de recommander un SellerAgent qui a
annoncé sa capacité de vendre cet article. Si plus d'un vendeur a annoncé un article, le
facilitant choisit aléatoirement un et renvoie le nom de ce SellerAgent à l'acheteur. Ceci
commence la communication entre l'acheteur et le vendeur pendant qu'ils essayent de
convenir sur un prix et clôturent l'affaire. Le facilitant agit en tant qu'intermédiaire entre
toutes les communications d'acheteur et de vendeur. Ceci nous permet d'observer l'échange
des messages entre les agents d'acheteur et de vendeur et de montrer une trace de ces
interactions dans le TextArea supérieur.
Toutes les communications entre les acheteurs, les vendeurs, et l'utilisation de facilitant
l'interface de CIAgentEvent et de CIAgentEventListener ont décrit en chapitre 7. L'objet
d'argument qui est passé avec le CIAgentEvents est un nouvel objet appelé un
CIAgentMessage, qui est modelé après un paquet standard de message de KQML. Bien que
nous n'analysions pas des messages de KQML dans cette application, l'utilisation de la classe
de CIAgentMessage devrait te donner une bonne sensation pour quelle application d'agent de
KQML regarderait comme (voir le chapitre 6 pour une description de KQML). Se rappeler
que KQML emploie des performatives pour indiquer l'action qu'il veut qu'un autre agent
prenne en son nom. Tandis que KQML spécifie le format et une partie du contenu de ces
interactions, les détails de nitty-gritty de la négociation d'Acheteur-Vendeur est jusqu'à
l'application à définir. La convention de négociation de ventes utilisée dans l'application de
marché est décrite dans la section suivante.
Après que tous les agents soient inscrits au facilitant et les vendeurs annoncent leurs articles,
le CIAgentMessages suivant sont échangés :
Un exemple
marché de Java
Le schéma 10.3 contient les messages de trace du facilitant qui apparaissent dans le TextArea
supérieur. Vous pouvez voir que le FacilitatorAgent est commencé quand () la méthode de
processus s'appelle et est arrêtée quand la méthode d'arrêt () s'appelle. La première
transaction entre l'acheteur et le vendeur est reflétée dans les lignes 6 à 12. Le schéma 10.4
contient les messages de trace des agents dans le marché. Les deux agents sont commencés
par () la méthode de processus. Quand le BuyerAgent se réveille, il annonce qu'il veut
acheter une guitare. L'échange des offres suit, et la transaction accomplit. Noter que c'est le
niveau récapitulatif de défaut des messages de trace. Si l'option de détails était choisie, des
informations supplémentaires seraient montrées, y compris le contenu du CIAgentMessages.
Comme vous pouvez voir, le BuyerAgent de base et le SellerAgent de base sont venus à un
prix de $175 pour les guitares, et à $325 pour les tambours. Ces prix sont beaucoup plus
élevés que les prix du but de l'acheteur. Des courses semblables peuvent être faites pour
l'acheteur intermédiaire et le vendeur intermédiaire, ou le meilleur acheteur peut être assorti
vers le haut contre le vendeur de base. Dans ce cas-ci, l'acheteur fait bien mieux ; suivant les
indications du schéma 10.5, il achète les trois instruments musicaux pour $500.
Ces exemples montrent l'opération de base et les interactions entre les agents dans le marché.
Dans les sections suivantes, la conception et les détails de l'exécution du FacilitatorAgent,
BuyerAgent, SellerAgent, les agents augmentés d'acheteur et de vendeur, et l'application
principale de marché elle-même sont décrits.
FacilitatorAgent
Le facilitant contient deux tables de brouillage, une qui sont un enregistrement pour tous les
agents dans le marché, et une qui contiennent les communautés de l'intérêt pour le marché.
Par exemple, il peut y avoir un ensemble de SellerAgents qui vend les instruments musicaux,
et un ensemble différent qui vend des billets d'avion. Ceux-ci sont groupés dans les
communautés ou des domaines. SellerAgents sont ajoutés à ces communautés en annonçant
leur volonté ou capacité de vendre un produit dans ce domaine. Juste parce qu'un agent
annonce quelque chose, cependant, ne signifie pas qu'elle peut vraiment fournir ce produit ou
service. Sans compter que le cas évident où le deviousness est impliqué, un vendeur sincère
peut annoncer un article one-of-a-kind. Un acheteur peut alors demander au facilitant de
recommander un vendeur pour cet article. Les négociations ont pu procéder entre le vendeur
et l'acheteur, ayant pour résultat une vente. En attendant, un autre acheteur pourrait demander
au facilitant de recommander un vendeur et quand il contacte le vendeur demandant un prix,
le vendeur niera qu'il a un tel article. Ce scénario pourrait être empêché si le vendeur rétracte
toujours ses annonces. Cette application fournit ces possibilités. Cependant, si les transactions
multiples continuent en même temps, un acheteur devra être déçu (ou le vendeur pourrait
LY_SII __ 230 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
vendre le même article à deux acheteurs, qui est non conformiste mais très profitable à court
terme).
runnit.start () ;
}
communauté. La logique spéciale est nécessaire pour traiter les cas où l'agent est le premier à
ajouter, ou dernier pour être enlevée d'une communauté.
Le premier performative de recommandation-un vérifie pour voir s'il y a des agents dans la
communauté d'intérêt. Si oui, le facilitant détermine combien d'agents ont annoncé et puis
roulent un à nombre aléatoire pour choisir on pour recommander au BuyerAgent. Le cas où
un BuyerAgent demande un SellerAgent, et aucun n'a annoncé, a comme conséquence un
état non défini dans l'application d'échantillon. Le BuyerAgent s'attend à une réponse de dire
du facilitant ce qui ne vient jamais. Une solution raisonnable ici serait d'envoyer un message
de nier de nouveau au BuyerAgent. Cependant, la logique d'état de BuyerAgent devrait être
mise à jour pour traiter ceci correctement.
si (communities.containsKey (msg.content)) {
Agents de vecteur = (vecteur) communities.get (msg.content) ;
agents.removeElement (expéditeur) ;
si == 0 (d'agents.size ()) communities.remove (msg.content) ;
}
retour ;
}
}
Agent de CIAgent = (CIAgent) agents.elementAt (index) ;
msg.performative = « indiquent » ;
msg.content = agent.name ;
msg.receiver = msg.sender ;
msg.sender = nom ; le facilitant d'exposition de // est expéditeur des msg
la construction de // un message d'anwser et l'envoient à l'agent
d'expéditeur
trace (« facilitant : Recommandé » + agent.name +
« à » + msg.receiver +
« pour » + article + « \ n ") ;
sender.ciaEventFired (nouveau CIAgentEvent (ceci, msg)) ;
} autrement {
trace (« facilitant : il n'y a aucun agent annonçant » +
msg.content + « \ n ") ;
}
retour ;
}
trace (« facilitant : acheminement » + msg.performative +
« message de » + msg.sender + « à » +
msg.receiver + « \ n ") ;
itinéraire de // le message à l'agent de récepteur
Récepteur de CIAgent = (CIAgent) allAgents.get (msg.receiver) ;
si (récepteur != nulle) {
receiver.ciaEventFired (nouveau CIAgentEvent (ceci, msg)) ;
} autrement {
// devrait indiquer à expéditeur que le récepteur ne pourrait pas être
trouvé ?
trace (« facilitant : récepteur » +
msg.receiver + « est inconnu ! \ n ") ;
}}
CIAgentMessage
Corde performative ;
Contenu de corde ;
inReplyTo de corde ;
Langue de corde ;
Ontology de corde ;
Récepteur de corde ;
LY_SII __ 234 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
replyWith de corde ;
Expéditeur de corde ;
BuyerAgent
La classe de BuyerAgent contient la fonctionnalité basse pour tous les acheteurs. Les
membres principaux de données incluent le wishList, un vecteur des articles que l'agent veut
acheter et des prix d'achat désirés ; l'inventaire, qui contient tous les articles le BuyerAgent a
acheté ; et les négociations, une table de brouillage des négociations en marche. () La
méthode de processus est employée pour enregistrer le BuyerAgent avec le facilitant global,
pour initialiser le wishList avec des exemples des objets de BasicNegotiation, et pour
commencer le fonctionnement du fil de l'agent. La méthode de course () fournit le corps du fil
de l'agent. Elle va dormir pendant 5 secondes, et puis s'il a toujours des articles sur son
wishList et aucune négociation n'est en marche, elle prend le premier article outre du wishList
et donne un coup de pied au loin une négociation en demandant au facilitant de recommander
un vendeur pour l'article. Elle fait ceci d'abord en instanciant un objet de CIAgentMessage et
en plaçant les fentes convenablement, et ensuite using elle comme argument pour un nouvel
objet de CIAgentEvent. Quand le BuyerAgent s'est inscrit au facilitant, le facilitant s'est
ajouté à la liste de CIAgentEventListener du BuyerAgent. Ainsi, appeler la méthode de
LY_SII __ 235 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
}
crochet (InterruptedException e)
{
// s'est interrompu
}
si ((wishList.size () > 0) && (en attendant la nulle de ==)) {
courant = (BasicNegotiation) wishList.firstElement () ;
en attendant = courant ; // nous avons une négociation en attente
wishList.removeElementAt (0) ;
trace (le nom + « regarde pour acheter » + current.offer.item +
« \ n ") ;
msg = nouveau CIAgentMessage (« recommander-un », current.offer.item,
annuler, le « vendeur », current.offer.item, nom) ;
CIAgentEvent e = nouveau CIAgentEvent (ceci, msg) ;
notifyCIAgentEventListeners (e) ; auditeurs de signal de //
}
trace (le nom + « a acheté » + inventory.size () +
« articles pour » + totalSpent + « \ n ") ;
}
}
…
} ;
Autrement, le message doit contenir une offre ou un contre-offre d'un vendeur. D'abord un
exemple d'une offre est créé. Une offre contient un triplet du nom d'article, de la marque
d'article, et du prix d'offre, avec le nom du vendeur faisant la proposition. Le constructeur
LY_SII __ 237 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
d'offre prend le CIAgentMessage comme paramètre et extrait l'information à partir des fentes
d'expéditeur et de contenu de message. Maintenant qu'une offre existe, nous devons
déterminer si c'est la première offre d'une nouvelle négociation ou si c'est un contre-offre dans
une négociation continue. Si un objet de BasicNegotiation existe dans la table de brouillage
de négociation avec la même marque d'article contenue dans l'offre, l'objet de
BasicNegotiation est mis à jour en passant la dernière offre suivre la méthode de newOffer ().
Si l'identification d'article n'est pas dans la table de brouillage, ce doit être la première offre
du SellerAgent. Le BuyerAgent prend la négociation en attente, lui fait le courant, place en
attendant pour annuler, et place la négociation sur la liste active.
Une autre alternative est que le vendeur rejette la dernière offre. Dans notre conception, ceci
finit les négociations. De nouveau, c'est une décision arbitraire, mais nous avons voulu rendre
explicite quand le vendeur décide de finir une négociation et de ne pas avoir l'essai de
BuyerAgent pour faire des contre-offres pour prolonger la négociation. Le BuyerAgent
nettoie la négociation de la liste et des endroits actifs il en arrière sur le wishList ainsi il peut
essayer encore en demandant au facilitant de recommander un autre vendeur pour l'article.
La troisième alternative est que le vendeur fait une proposition et le BuyerAgent doit
négocier using (quoi encore ?) négocier () la méthode. La sophistication de la logique de
traitement dans cette méthode est le point primaire de différentiation entre notre BuyerAgent
de base, le BetterBuyerAgent, et les classes de BestBuyerAgent.
si (negotiations.containsKey (offer.id)) {
courant = (BasicNegotiation) negotiations.get (offer.id) ;
} autrement {
courant = en suspens ; // obtiennent la négociation en suspens
en attendant = nulle ; // aucuns articles en suspens
negotiations.put (offer.id, courants) ; endroit de // sur la liste active
}
current.newOffer (offre) ; mise à jour de // l'objet de négociation
Le BuyerAgent de base vérifie si le prix d'offre du vendeur est inférieur au strikePrice, qui
est le prix maxima désiré. S'il est, il accepte l'offre en faisant écho le message de nouveau au
vendeur, supposant que le SellerAgent acceptera la proposition qu'il a juste faite. Si le prix
d'offre est plus élevé que l'acheteur est disposé à payer, le BuyerAgent doit faire une contre-
proposition (se rappeler, dans cette conception, seulement le vendeur peut rejeter une offre).
L'agent de base taille simplement $25 outre du prix du vendeur et fait une proposition dans les
LY_SII __ 239 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
espoirs que le vendeur acceptera. Plus tard en ce chapitre, nous explorerons les stratégies plus
sophistiquées employées par nos agents de BetterBuyer et de BestBuyer.
SellerAgent
La classe de SellerAgent contient la fonctionnalité basse pour tous les vendeurs. Les
membres principaux de données incluent l'inventaire, une table de brouillage des articles que
l'agent veut se vendre et des prix de ventes désirés, et les négociations, une table de
brouillage des négociations en marche. () La méthode de processus est employée pour
enregistrer le SellerAgent avec le facilitant global, initialise l'inventaire avec des exemples
des objets de BasicNegotiation, annonce les articles au facilitant, et pour commencer le
fonctionnement du fil de l'agent. La méthode de course () fournit le corps du fil de l'agent.
Elle va dormir pendant 15 secondes et puis rapporte le statut de son inventaire.
Après que le SellerAgent annonce ses articles au facilitant, il doit attendre un BuyerAgent
éventuel pour entrer en contact avec le facilitant recherchant une recommandation d'un
vendeur probable. Quand le facilitant passe le nom du SellerAgent au BuyerAgent,
l'acheteur envoie un message de demand pour commencer les négociations. Comme le
BuyerAgent décrit plus tôt, le SellerAgent reçoit n'importe quel message comme argument
d'un CIAgentEvent par () la méthode ciaEventFired. La méthode de processMessage ()
interprète le message et détermine la réponse appropriée.
} ;
La méthode de processMessage () doit prendre soin de deux cas de base. Est d'abord répondre
à une initiale demandent d'un BuyerAgent, et l'autre est de répondre à une offre. Dans le
premier cas, il y a beaucoup de ménage à faire quand un BuyerAgent pose des questions sur
un article. D'abord, il doit vérifier pour voir s'il a toujours les articles désirés l'uns des dans
l'inventaire (comme décrit plus tôt, il pourrait avoir juste vendu dernier). L'assumer a l'article,
il produit alors d'une marque unique d'article en appelant la méthode de genID (). La marque
d'article est le nom du SellerAgent enchaîné avec un nombre entier nonrepeating (par
exemple, Seller1, ou BetterSeller3). Cette marque d'article est alors employée comme clef de
table de brouillage des objets pour d'acheteur et de vendeur négociation. L'objet de
BasicNegotiation de l'article est enlevé de la liste d'inventaire, le membre d'identification
d'article est placé, et le champ de lastOffer est initialisé au prix de vente minimum plus $100.
Le SellerAgent place alors le BasicNegotiation sur les négociations actives énumèrent, et
envoient faire-offrent le message de nouveau au BuyerAgent par le facilitant qui est un
CIAgentEventListener enregistré.
Dans le deuxième cas, il y a une négociation en marche. Le SellerAgent instancie une offre
du CIAgentMessage et recherche la négociation des négociations actives énumèrent, using
l'identification d'article comme clef de table de brouillage. S'il n'y a aucun objet de
BasicNegotiation avec cette identification d'article, elle doit avoir été juste vendue, ainsi le
SellerAgent envoie rejeter-offrent le message au BuyerAgent. Autrement, il met à jour le
BasicNegotioation avec l'offre courante. Après, il détermine si l'acheteur fait une contre-
proposition ou en reconnaissant simplement un précédent accepter-offrir le message. Si c'est
un dire, ce doit être le dernier cas, un article a été juste vendu. Le BasicNegotiation est
enlevé des négociations actives énumèrent, et le prix d'achat est ajouté au total de ventes.
LY_SII __ 242 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Dans le SellerAgent de base, si le prix d'offre de l'acheteur est au-dessus du prix de vente
minimum désiré, l'offre est immédiatement acceptée et un message est renvoyé au
BuyerAgent. Le BuyerAgent doit reconnaître l'offre avec un message de dire avant que
l'article puisse être enlevé de l'inventaire. Si le BuyerAgent offre moins que le SellerAgent
est disposé à prendre pour l'article, l'offre est rejetée et les négociations sont clôturées en
plaçant l'article en arrière dans l'inventaire (se rappeler, ceci est l'agent de base).
Dans cette section, nous décrivons des améliorations à notre acheteur et SellerAgents de base.
Ces agents augmentés prolongent les classes de BuyerAgent et de SellerAgent,
principalement en dépassant les méthodes de négociation (), et en utilisant des informations
supplémentaires au sujet du processus de négociation. Le BetterBuyerAgent et le
BetterSellerAgent emploient la logique hardcoded avec une stratégie légèrement plus
agressive de négociation et ne justifient aucune autre discussion. Le BestBuyerAgent et le
LY_SII __ 245 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
En plus des règles qui calculent la valeur de l'offerDelta, il y a deux ou trois règles d'action.
Ces règles ont EffectorClauses en tant que leur conséquent. Quand ils mettent le feu, ils
appellent () la méthode effectrice définie dans BestBuyerAgent. Comme décrit plus tôt, les
agents d'acheteur peuvent seulement faire des propositions au SellerAgents. Si le chaînage
avant inferencing décide de faire une contre- proposition ou de l'accepter, () la méthode
effectrice s'appelle par la règle d'action, et le message est envoyé directement de la mise à feu
de règle. Une conception alternative, si le RuleBase ne soutenait pas des règles d'effecteur ou
d'action, serait de calculer l'offerDelta et de faire déterminer la logique hardcoded examiner la
valeur et quelle action pour exécuter.
-
LY_SII __ 246 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
La méthode première de négociation () remet à zéro la base et puis les calculs de règle et
place la valeur de la diffusion. Un essai spécial est ajouté pour voir si l'offre précédente et
l'offre courante sont identiques. Si oui, ce signifie que l'acheteur a accepté l'offre, et la valeur
de la diffusion soit placée à >50 pour forcer accepter-offrent l'action. Évidemment, accepter
pourrait s'être appelé directement, mais dans ce cas-ci, nous voulons démontrer le mécanisme
d'action de RuleBase.
LY_SII __ 247 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Dans l'essai avec le BestBuyerAgent et le BestSellerAgent basés sur les règles, nous avons
constaté que les agents pourraient entrer dans les boucles infinies négociant dans les deux
sens. Le membre d'itération a été ajouté à la classe de BasicNegotiation pour maintenir ceci
et pour court-circuiter ces boucles quand elles se produisent. Cependant, dans de vrais
systèmes multiagent il y a toujours la possibilité de produire des orages ou des impasses de
message entre les agents. Des mécanismes de sécurité pour détecter et éviter ces conditions
doivent être inclus dans des réalisations commerciales.
Un cycle d'inférence de chaînage avant est exécuté. La quantité de la contre- offre (le cas
échéant) est calculée, et l'action ou l'effecteur () que des méthodes s'appellent pendant le
processus inferencing. () La méthode effectrice contient la logique pour interpréter la valeur
de l'offerDelta RuleVariable, selon lequel l'effecteur a été appelé.
--
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Application de marché
Nous précisons une partie de la logique unique d'application priée pour mettre en application
le marché de CIAgent. Les sept CIAgents, le FacilitatorAgent, et les trois types de
l'acheteur et du SellerAgents sont des membres de données de la classe d'application de
marché.
-
LY_SII __ 248 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Discussion
Dans cette section, nous décrivons le raisonnement derrière certaines des décisions de
conception prises tout en développant l'application de marché.
Peut-être la première décision que nous avons prise était le choix de l'utilisation KQML-
comme CIAgentMessage au lieu vrais » messages de KQML d'analyse des « . Notre
sentiment était que nous pourrions explorer plusieurs des questions des communications
d'agent using la classe de CIAgentMessage sans obtenir embourbés dans les complexités
d'analyser des rapports de KQML. Nous avons traité les issues liées à l'utilisation des
performatives de KQML et à l'entretien des états de conversation entre le facilitant et les
agents d'acheteur et de vendeur.
Également, comme peut avoir déjà été évident, nous n'avons pas dépensé des stratégies
optimales se développantes beaucoup de temps de négociation pour le BuyerAgent et le
SellerAgents. Comme nous avons énoncé, notre but était de montrer le progrès des agents de
hardcoded simple à basé sur les règles plus complexe, et de montrer les avantages de la
sophistication accrue dans l'exécution de ligne de fond des algorithmes. On pourrait
facilement imaginer hardcoding une meilleure stratégie que nous avons employé dans le
BestBuyerAgent et le BestSellerAgent. Mais le point était d'illustrer la puissance et la
flexibilité d'utiliser un moteur basé sur les règles pour commander les négociations et pour
prendre directement les mesures suivre () les méthodes effectrices.
LY_SII __ 249 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Une simplification utilisée dans la stratégie de négociation était que le SellerAgent a enlevé
l'article de l'inventaire dès qu'un acheteur s'est enquis de. Ceci a empêché deux négociations
continuant en même temps pour le même article. Tandis que dans un vrai marché cette sorte
de chose entre toute les heure, la complexité supplémentaire de cette approche semble être
supérieure aux avantages.
Résumé
En ce chapitre, nous avons développé une application électronique de marché using sept
CIAgent-avons basé les agents intelligents. Les questions principales incluent :
Exercices
Chapitre 11
Environnements d'agent du Java-Based
Nous concluons avec un examen d'autre les environnements Java-basés d'agent.
Tandis que ce n'est pas une liste approfondie d'agents Java-basés, il fournit une
vue d'ensemble de ce qui se produit dans l'industrie, d'où le foyer est, et ce qui
plus doit être fait pour apporter à Java les agents intelligents à leur pleine
capacité.
Ferrets
Les ferrets sont les agents autonomes Java-basés développés par IBM. Ils fournissent les
possibilités de base exigées pour la mobilité. Chaque ferret a le nom unique d'a globalement -.
Un itinéraire de voyage est employé pour spécifier les destinations auxquelles l'agent doit
voyager et quelles mesures il doit prendre à chaque endroit. Pour qu'un ferret coure sur un
système particulier, ce système doit courir une application de centre serveur de ferret. Ceci
fournit un environnement plate--neutre d'exécution pour le ferret. L'établi de ferret inclut un
directeur de sécurité configurable de Java, qui peut limiter l'activité d'un ferret sur le système
de la même manière que le directeur de sécurité de défaut est habitué pour limiter les activités
d'un applet.
Les ferrets peuvent communiquer using un whiteboard qui permet à des agents de collaborer
et de partager l'information asynchrone. Le dépassement synchrone et asynchrone de message
est également soutenu pour la communication de ferret. Des ferrets sont coulés using la
fabrication en série ou l'externalisation standard de Java. On fournit un chargeur de classe
d'agent de réseau qui permet le jet et l'état du bytecode d'un ferret au voyage à travers un
réseau.
Tandis que les ferrets ne sont pas en soi intelligents, ils sont écrits dans Java et peuvent être
prolongés avec le code intelligent l'un des de Java que nous avons fourni dans les chapitres
premiers de ce livre. Pour plus d'information sur des ferrets, voir le
http://www.trl.ibm.co.jp/aglets/.
La technologie d'agent de logiciel de ftp est logiciel Java-basé conçu pour contrôler les
réseaux hétérogènes à travers l'Internet using la technologie d'agent. Les agents sont
autonomes et mobiles, et peuvent se déplacer à n'importe quel système dans le réseau qui a un
répondeur d'agent installé. Pendant que l'agent se déplace de système/système, ses tâches
peuvent changer, selon l'environnement du système qu'il visite.
Les agents peuvent agir l'un sur l'autre avec d'autres agents ou avec l'utilisateur, comme
nécessaire. Mais les agents de ftp n'exigent aucun utilisateur interaction-basé sur la
technologie de « poussée », ils peuvent se déplacer de système/système, répondre aux
événements, et effectuer des tâches selon des critères prédéfinis par l'utilisateur. Un directeur
d'agent est responsable de lancer l'agent.
LY_SII __ 252 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Deux applications sont disponibles employant cette technologie d'agent : Auditeur d'IP et
distributeur d'IP. L'application d'auditeur d'IP emploie des agents pour collecter le matériel, le
logiciel, et les informations de configuration pour des systèmes dans un réseau. L'application
de distributeur d'IP distribuera le logiciel et exécutera sur option des fonctions sur des
systèmes de cible dans un réseau.
La littérature sur la technologie d'agent de logiciel de ftp décrit les agents comme
« intelligents, » mais l'intelligence a été défini dans ce contexte comme ayant la capacité de
transporter des données et des instructions, d'analyser l'environnement de cible, et de répondre
aux conditions a trouvé au système de cible. Il ne semble pas se rapporter à inferencing basé
sur les règles ou à machine apprenant comme décrit plus tôt dans ce livre. Des détails sur des
agents de logiciel de ftp peuvent être trouvés chez http:/www.ftp.com/.
Voyager
Les agents de Voyager ont la mobilité et l'autonomie qui est fournie dans la classe basse,
agent. Un agent peut se déplacer d'un endroit à l'autre et peut laisser une adresse d'expédition
avec un « secrétaire » de sorte que de futurs messages puissent être expédiés à son nouvel
endroit. Des agents spécialisés, appelés Messengers, sont employés pour fournir des
messages. Les messages peuvent être synchrones, à sens unique (semblable à asynchrone), ou
un futur, qui sont asynchrones mais renvoient un texte d'attente qui peut être employé pour
rechercher une valeur de retour à un temps postérieur.
Comme des ferrets, l'itinéraire d'un agent instruit l'agent quant à quelles opérations il doit
effectuer à chaque endroit. En outre, comme des ferrets, Voyager emploie la fabrication en
série pour couler l'état de l'agent pendant que l'agent se déplace de l'endroit à l'endroit.
Voyager inclut également un directeur de sécurité qui peut être employé pour limiter les
opérations qu'un agent peut effectuer. À l'avenir, Voyager sera augmenté avec un modèle de
sécurité basé sur les règles qui complète le mécanisme de sécurité standard de Java.
Les agents de Voyager eux-mêmes ne sont pas en soi intelligents. Ils ne contiennent un
moteur d'inférence, des réseaux neurologiques, ou aucune autre technologie d'intelligence
artificielle. Mais, comme des ferrets, ils peuvent être augmentés avec des techniques l'unes
des d'intelligence artificielle décrites dans ce livre. Des informations supplémentaires sur
Voyager peuvent être trouvées chez http://www.objectspace.com/.
Odyssée
LY_SII __ 253 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
Le système d'agent de l'odyssée de la magie générale est un ensemble de classes de Java qui
soutiennent des agents d'odyssée, des systèmes d'agent, et des endroits. Des agents sont créés
par subclassing la classe d'agent ou la classe d'ouvrier. Chaque agent s'exécute en son propre
fil de Java, et peut voyager d'un endroit à l'autre. À chaque nouvel endroit, cependant, le fil
doit être remis en marche. Un exemple de la classe d'endroit définit l'environnement
d'exécution pour un agent sur chaque système hôte. Un ouvrier est une spécialisation de la
classe d'agent. Un ouvrier contient un itinéraire qui est un ensemble de tâches et de
destinations. L'ouvrier exécute une tâche à chaque centre serveur de destination. Le système
d'agent d'odyssée fournit également des classes de soutien telles que le billet, qui définit
comment et où un agent peut voyager, et la pétition, qui identifie d'autres agents avec qui
l'agent souhaite communiquer.
L'odyssée est écrite entièrement dans Java et exige JDK 1.1. Elle emploie le RMI en tant que
son transport, mais peut également être configurée pour employer le modèle composant
distribué de Microsoft (DCOM) ou le protocole d'Inter-CORPS ROND d'Internet. Un CORPS
ROND n'est pas inclus en tant qu'élément du système d'odyssée, mais se fonde à la place sur
l'installation de VisiBroker de Visigenic pour Java. Même si DCOM ou IIOP est employé,
l'enregistrement de RMI est encore nécessaire par le trouveur, qui détermine où un endroit
particulier est localisé. À la différence des ferrets ou de Voyager, l'odyssée n'inclut pas son
propre SecurityManager, et se fonde seulement sur les mécanismes de sécurité standard de
Java.
Comme les autres agents décrits en ce chapitre, des agents d'odyssée ne sont pas dotés
d'intelligence, mais, parce qu'ils sont écrits dans Java, peuvent être augmentés par les
techniques d'intelligence artificielle démontrées par le CIAgents dans ce livre. Pour plus
d'information sur des agents d'odyssée, voir le http://www.genmagic.com
JATLite
Le calibre Lite (JATLite) d'agent de Java est un ensemble de paquets légers de Java étant
développés à l'Université de Stanford qui peut être employée pour établir les systèmes
multiagent. C'est une architecture en couches qui fournit un protocole de transmission
différent à chaque couche. La couche la plus bottom-most fournit seulement les classes
abstraites qui peuvent être mises en application pour soutenir n'importe quel protocole de
transmission. La couche basse emploie le TCP/IP comme mécanisme de communication et
permet aux applicateurs d'agent de définir le protocole de message. La couche de KQML
fournit l'appui pour les agents qui emploient des messages de KQML. La couche de routeur
ajoute le cheminement de message qui permet à des messages d'être alignés pour les agents
qui ne sont pas en activité quand le message est reçu par le routeur.
Le centre de JATLite est évidemment sur la communication. Comme plusieurs des autres
environnements d'agent discutés en ce chapitre, n'importe quelle intelligence devrait être
fournie par les applicateurs d'agent using des techniques décrites plus tôt dans ce livre. Pour
LY_SII __ 254 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
InfoSleuth
InfoSleuth est un projet de recherche au MCC qui emploie des agents pour trouver,
rechercher, et intégrer des informations des points d'émission hétérogènes. Son architecture
est basée sur les agents autonomes de coopération qui annoncent leurs services et traitent des
demandes de ces services. Elle est basée sur KQML, KIF, HTTP, et technologies de Java.
KQML est employé comme format et protocole de message standard entre les agents. Le
projet d'InfoSleuth inclut une exécution de Java de la langue et de protocole de KQML. KIF
est employé pour échanger la connaissance entre les agents. Les agents convertissent
l'information de leurs formats internes en KIF et emballage il dans un KQML performative
avant d'envoyer le message à un autre agent.
À la couche la plus bottom-most dans l'architecture d'InfoSleuth sont les agents basés sur les
règles écrits en une série de langues comprenant blèsent (un langage de programmation liste-
basé d'AI), LDL++ (une langue déclarative de base de données qui inclut inferencing basé sur
les règles), AGRAFES (un système expert basé sur les règles), et Java. Puisque KQML et KIF
sont employés pour l'échange d'information, il n'est pas que tous les agents soient mis en
application dans un unilingue. Sur la coopérative les agents est une couche d'ontologies qui
inclut les agents qui emploient un vocabulaire commun et un modèle sémantique pour chaque
domaine particulier de problème. Des applications sont écrites sur la couche d'ontologies de
l'architecture.
Un certain nombre d'agents sont employés dans les différentes couches de l'architecture. Les
agents d'utilisateur, écrits dans Java, des demandes de poignée des utilisateurs, conduisent les
demandes aux agents de serveur, et renvoient les résultats à l'utilisateur. Ils sont persistants et
autonomes, qui leur permet de courir des tâches pour des utilisateurs même lorsque
l'utilisateur n'agit l'un sur l'autre plus avec l'agent. Les agents d'utilisateur contiennent
également l'intelligence de modeler le comportement de l'utilisateur. Pour faire ceci, ils
agissent l'un sur l'autre avec d'autres agents de Java appelés les moniteurs. Un moniteur
dépiste l'accès et les rapports du Web d'un utilisateur il à l'agent d'utilisateur pour l'usage dans
la détection inferencing et de modèle.
L'agent de courtier est un autre agent de Java qui est semblable au facilitant dans notre
application de marché. Elle assortit des demandes des agents avec les agents de serveur
d'ontology qui annoncent les ontologies pour lesquels ils ont la responsabilité. Les agents
d'ontology agissent l'un sur l'autre avec les agents d'exécution qui sont responsables d'exécuter
les questions ontology-basées. Les agents d'exécution fonctionnent avec les agents de
ressource qui sont les embouts avant intelligents au datastore fondamental. Les données
renvoyées d'une question peuvent également être passées aux agents d'analyse de données qui
effectuent l'analyse, l'exploitation de la connaissance, et les tâches intelligentes de
reconnaissance des structures sur les données.
Tandis que Java n'était pas la seule langue employée pour construire InfoSleuth, il a été
employé dans toute l'exécution. Des applet et la sécurité d'applet ont été employés sans risque
pour distribuer et regarder les données. La nature plate--indépendante de Java a également
LY_SII __ 255 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
permis pour déployer les agents dans l'environnement hétérogène pour lequel InfoSleuth a été
développé. Tandis que des AGRAFES et d'autres langues basées sur les règles étaient utilisées
pour fournir une grande partie de l'intelligence, certains des agents ont compté sur
l'intelligence mise en application seulement dans Java. Plus d'information sur InfoSleuth peut
être trouvée chez http://www.mcc.com/projects/infosleuth.
Jess
Jess n'est pas un environnement d'agent, intrinsèquement, mais est une exécution subsetted du
système expert générique d'AGRAFES écrit dans Java. Il peut être employé pour donner des
applications de Java, des applet, et des agents la capacité de raisonner using une base de règle
d'AGRAFES.
Des AGRAFES (système de production Integrated de langage C) ont été développées par le
centre spatial de Johnson de la NASA et ont été autorisées près plus de 4.000 publics et
établissements privés. C'est un système basé sur les règles de chaînage avant, basé sur
l'algorithme de Rete. Le code écrit dans la langue d'AGRAFES peut être couru par Jess.
Jess est une application de Java qui peut être courue de la ligne de commande comme
n'importe quelle autre application de Java. Mais le paquet de Jess contient également les
classes qui permettent à des applications ou à des applet de Java d'appeler le moteur de
système expert (la classe de Rete) ou l'analyseur de Jess (la classe de Jesp). Ceci permet aux
agents de Java d'être développés qui peuvent traiter les bases de connaissances de
préexistence d'AGRAFES. Pour l'information sur Jess, voir le
http://herzberg.ca.sandia.gov/jess/.
ABE
Un des différentiateurs principaux entre ABE et la plupart des autres environnements Java-
basés d'agent est qu'il est concentré sur la partie « intelligente » d'agents intelligents. Tandis
qu'IBM a des ferrets pour les agents mobiles de Java, ABE fournit un moteur basé sur les
règles puissant de raisonnement pour commander le comportement de l'agent. Ce moteur basé
sur les règles, appelé l'AUGMENTER, a été développé au centre de recherches d'IBM T.J.
Watson et est le coeur d'ABE. Il soutient une approche souple pour les sondes de
configuration et les effecteur à l'usage de l'agent en tant que lui raisonne au sujet du monde.
L'ABE est plus qu'un agent, il est une architecture et une trousse à outils pour les agents
révélateurs. ABE se compose de plusieurs composants importants, y compris des moteurs, la
connaissance, la bibliothèque, des vues, et des adapteurs. Le moteur dans ABE est le
moteur basé sur les règles d'AUGMENTER, mais l'architecture soutient le concept des
moteurs que l'on peut brancher. La connaissance est représentée dans KIF, et un rédacteur
Java-basé de GUI est donné pour écrire de règle. ABE fournit également un composant
LY_SII __ 256 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
flexible de bibliothèque pour stocker les ensembles et les méta-données appelés de règle de
KIF. Le composant de vue définit comment des rédacteurs et les dialogues peuvent être
attachés par des adapteurs d'ABE pour fournir à la séparation propre de modèle-vue entre le
traitement intelligent de l'agent et les interactions d'agent des utilisateurs.
Des adapteurs sont utilisés pour connecter les agents d'ABE et le moteur d'inférence
d'AUGMENTER aux applications. Par exemple, ABE vient avec des adapteurs les serveurs de
nouvelles à du World Wide Web (HTTP), de l'Internet (NNTP), un adapteur de temps qui
déclenche des événements basés sur le temps, et un adapteur de dossier ce des événements de
déclenchements quand des dossiers sont changés. Ces adapteurs fournissent un ensemble de
fonctions beaucoup plus riche que ceux fournis dans l'exécution CIAgent-basée développée
dans ce livre. Des adapteurs témoin à se connecter par interface aux systèmes d'email et pour
observer des cours des actions d'actions à un site Web sont également inclus. Ces adapteurs
peuvent être écrits dans Java et ils peuvent entièrement interopérer avec d'autres adapteurs de
Java ou de C++ par l'ABE. Pour l'information sur l'environnement de constructeur de l'agent
d'IBM, voir le http://www.networking.ibm.com/iag/iaghome.html.
Discussion
La majeure partie de la recherche pour ce chapitre a été faite sur le World Wide Web. Pendant
notre recherche de l'information sur les outils et les produits Java-basés, il était clair qu'il y ait
beaucoup d'activité dans ce secteur. En même temps, il est également évident que plusieurs
des outils d'agent aient été concentrés plus sur la mobilité d'agent que sur l'intelligence
artificielle. Sans exception, on a assumé que des agents sont autonomes, ainsi il semble que au
moins cet attribut est convenu.
Nous avons essayé de choisir l'ensemble de ce qui a semblé être les environnements d'agent
de Java les plus complets. Nous n'avons pas téléchargé et n'avons pas essayé tous les outils
mentionnés en ce chapitre. Mais des systèmes que nous avons examinés, quelques modèles
clairs pourrait être identifié. KQML a été cité dans plusieurs comme protocole de transmission
interagent. KIF a été cité dans plusieurs autres comme représentation de connaissance. Dans
les quelques systèmes où l'intelligence artificielle était le traitement inclus et basé sur les
règles était un dispositif assez standard. L'étude, cependant, n'a pas été incluse dans la plupart
des systèmes.
Comme avec d'autres secteurs de nouvelle technologie, il semble que les agents intelligents ne
seront pas un « marché » seuls. Au lieu de cela, ils seront enfoncés dans des applications
économiques où ils peuvent fournir la valeur la plus immédiate, et se transforment lentement
en la fourniture devoir-ont des dispositifs dans le logiciel commercial. Comme cité
précédemment, l'autonomie est maintenant donné pour les agents intelligents. La mobilité a
clairement l'appel, mais il n'est pas clair si ceci fasse appel aux lotisseurs ou aux utilisateurs
potentiels. La sécurité et l'infrastructure exigées pour que les agents mobiles se déplacent
facilement autour de l'Internet peuvent simplement être trop d'un obstacle.
L'intelligence sera employée dans les agents où le domaine d'application l'exige. Pour
beaucoup d'applications aujourd'hui, il semble que la logique hardcoded suffira. Là où plus de
flexibilité est exigée, inferencing basé sur les règles est inclus. Typiquement ce sont les
moteurs d'inférence assez légers, en ce qui concerne la fonction traditionnelle d'AI. Dans
LY_SII __ 257 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
beaucoup d'applications, telles que l'automation d'email, le traitement de règle simple est tout
ce qui est exigé.
L'étude suivra probablement ce même modèle. Les frais généraux informatiques des
algorithmes d'étude communs font à leur utilisation un luxe pour la plupart des applications.
Cependant, parce que les agents intelligents basés sur des serveurs d'Internet, où leur capacité
d'interpréter des données et des modèles dans les transactions ajouterait la valeur significative,
l'étude peut rapidement devenir une nécessité. Les outils du filtrage de collaboration du réseau
de luciole utilisent l'étude pour fournir la personnalisation intelligente et les communautés en
ligne adaptatives pour des compagnies fournissant des sites Web du haut-trafic. La
technologie d'étude de luciole peut être employée pour élaborer une liste personnalisée du
principal 10 pour des utilisateurs sans exiger des mots-clés ou écrire de règle
(http://www.firefly.com).
Jusque Java et agents intelligents vont, elle semble comme une allumette faite dans le ciel. La
fonction intégrée de Java filetant l'appui permet à l'autonomie d'être facilement ajoutée à
n'importe quelle classe de Java. Son appui de fabrication en série et possibilités à distance
d'invocation de méthode rendent la mobilité loin moins intimidante qu'avec d'autres langages
de programmation. En conclusion, son appui de programmation orientée objectivement de
vers le bas-à-le-noyau permet à des algorithmes d'intelligence artificielle d'être facilement mis
en application, comme nous espérons que nous avons démontré dans ce livre.
Résumé
• Les ferrets sont le cadre autonome et mobile d'IBM de Java d'agent. Les ferrets sont
libres pour errer entre les serveurs courant le logiciel de centre serveur de ferret et
peuvent suivre un itinéraire prédéfini de voyage. Un processus de ferret peut être
suspendu, transporté à un autre système hôte de ferret, et à un résumé comme si il n'a
été jamais arrêté.
• Les agents de logiciel de ftp sont les agents Java-basés de gestion-système de réseau
et de distribution de logiciel.
• Le système de Voyager, d'ObjectSpace, Inc., est un courtier de demande d'objet
agent-augmenté écrit dans Java. Les agents de Voyager sont autonomes et mobiles,
mais non intelligents.
LY_SII __ 258 ْﺑــــــــــــــــﺴْﻢِ اﷲ اﻟﺮَﺣْﻤَـــــــــــــــﺎن اﻟﺮَﺣِﯿــــــــــــــــــــــﻢ
• L'odyssée est le système d'agent de Java de la magie générale. Écrit entièrement dans
Java, les agents d'odyssée emploient le RMI et sont autonomes et mobiles, mais non
intelligents.
• Le calibre Lite (JATLite) d'agent de Java est un ensemble de paquets légers de Java
développés à l'Université de Stanford. JATLite fournit une architecture en couches
pour les systèmes multiagent de bâtiment.
• InfoSleuth est un projet de recherche au MCC qui emploie des agents pour trouver,
rechercher, et intégrer des informations des points d'émission hétérogènes. Il emploie
KQML et KIF pour la communication et la représentation de connaissance et fournit
les agents basés sur les règles dans Java.
• Système expert générique Java est une exécution de Java de l'environnement
standard de base de règle d'AGRAFES développé au laboratoire national de Sandia.
Tandis que pas un environnement d'agent, Jess fournit l'appui inferencing basé sur les
règles dans Java.
• L'environnement de constructeur d'agent développé à IBM est une trousse à outils
d'architecture et de développement d'agent intelligent pour ajouter les agents
incorporés aux applications. Le moteur d'inférence d'AUGMENTER est utilisé comme
contrôleur d'agent, avec KIF ordonne et soutien de bibliothèque de stockage de la
connaissance et de méta-données. L'architecture d'ABE inclut les adapteurs qui se
connectent par interface directement aux applications et communiquent avec le moteur
d'AUGMENTER par des sondes et des effecteur.
• La situation actuelle des agents intelligents de Java est qu'ils sont autonomes et
mobiles, mais pas très intelligent. Là où l'intelligence artificielle est utilisée, le plus
souvent elle est par inferencing basé sur les règles, et rarement avec l'étude. Le futur
pour Java et agents intelligents semble lumineux.