首页> 中国专利> 使用自适应面向代理软件结构的自适应交互

使用自适应面向代理软件结构的自适应交互

摘要

处理主题消息的方法和代理网络结构,其中每个代理具有它自己职责范围概念。接收用户输入请求但本身没有相应解释策略的启动器代理询问它的下行链路代理:被询问代理是否认为这种消息是在它的职责范围内。每个被询问的代理递归地确定它是否具有适用于该请求的它自己的解释策略,如果没有,则进一步询问它自己的更进一步下行链路邻居代理。更进一步代理最终响应这种进一步询问,从而允许第一被询问代理响应该启动器代理。这一程序的递归调用最终确定经该网络从启动器代理到一个或多个分支代理的一个或多个路径。然后该请求沿路径向下传送,沿线的每个代理在其上采取任何本地操作并把该消息传送给该路径上的下一个代理。如果出现矛盾,网络经常能够根据预定的算法解决这样的矛盾,如果它不能自动解决一个矛盾,则它学习正确解释主题消息的所必需的新解释策略。这种学习最好包括与用户交互(但仅限于所需范围),并且最好把这种学习限制为接近网络中的正确分支代理位置。

著录项

  • 公开/公告号CN1312925A

    专利类型发明专利

  • 公开/公告日2001-09-12

    原文格式PDF

  • 申请/专利权人 德吉马公司;

    申请/专利号CN99809697.0

  • 申请日1999-06-14

  • 分类号G06F17/30;

  • 代理机构柳沈知识产权律师事务所;

  • 代理人黄小临

  • 地址 美国加利福尼亚州

  • 入库时间 2023-12-17 13:58:38

法律信息

  • 法律状态公告日

    法律状态信息

    法律状态

  • 2010-09-01

    未缴年费专利权终止 IPC(主分类):G06F17/30 授权公告日:20081112 申请日:19990614

    专利权的终止

  • 2008-11-12

    授权

    授权

  • 2008-02-13

    专利申请权、专利权的转移(专利申请权的转移) 变更前: 变更后: 登记生效日:20080111 申请日:19990614

    专利申请权、专利权的转移(专利申请权的转移)

  • 2001-09-19

    实质审查的生效

    实质审查的生效

  • 2001-09-12

    公开

    公开

说明书

该专利文件的公开部分含有受到版权保护的材料。版权所有者不反对按美国专利商标局文件或记录发表的专利文件或专利公开物的任何一种复制,但保留任何其它的版权。

本申请要求于1998年6月15日提交的第60/089,394(代理人案号,第DEJI-1000SUPO WSW)美国临时申请的权益,该临时申请作为参考文件引出。

背景

1.发明领域

本发明涉及用户机器接口,特别是实现对用户机器接口有用的面向代理的结构的软件方法和技术。

2.参考

下面的文件作为参考而引出。

T.Kuhme,自适应行动提示-支持探测用户接口中的面向任务交互作用的补充帮助,报告#GIT-GVU-93-19,乔治亚州技术学院计算机科学、制图技术、显象技术系和可用性中心,1993年。

L.Balint,自适应动态菜单系统,海报摘要,波士顿HCI(计算机接口)国际会议89,1989年九月18-22日。

A Cypher.Eager;依据样本对重复性任务编程,Proc(会刊),CHI91,pp.33-39,1991。

R.Beale,A.Wood,基于代理的交互作用,格拉斯哥(Glasgow)HCT’94会议论文集,1995,pp.239-245。

A.Wood,“Desktop Agents(桌面代理)”,伯明翰大学计算机科学学院,理学士学位论文,1991。

Clarke,Smyth,“基于人类合作原则的合作计算机”,机器人研究国际期刊38,pp.3-22,1993。

N.Eisenger,N.Elshiewy,MADMAN-Multi-Agent Diary Manager(多代理日志管理器),ESRC-92-7i(经济和社会资源委员会)内部报告,1992。

T.Oren,G.Salomon,K.Kreitman,A.Don,人机接口设计技术,“Guides:Characterizing The Interface(指南:表征接口)”,BrendaLaurel(ed.),1990(pp.367-381)。

F.Menczer.R.k.Belew,Adaptive Information Agents in DistributedTextual Environments(分布式文本环境中的自适应信息代理),Proceeding ofthe Second  International Conference on Autonomous Agents(关于自控代理的第二次国际会议的会议论文)(Agents’98),Minneapolis,MN,May 1998.

P.Brazdil,M.Gams,S.Sian,L.Torgo,W van de Velde,Learning inDistributed Systems and Multi-Agent Environments(在分布式系统和多代理环境中学习),http://www.ncc.up.pt/~ltorgo/Papers/LDSME/LDSME-Contents.html(visited 1998)。

B.Hodjat,M.Amamiya,The Self-organizing symbiotic agent(自组织共生代理),http://www_al.is.kyushu-u.acjp/~bobby/lstpaper.htm,1998.

P.R.Cohen,A.Cheyer,M.Wang,S.C.Baeg,OAA: An Open Agentarchitecture(开放的代理结构),AAAI Spring Symposium(AAAI春季讨论会),1994,http://www.ai.sri.com/~cheyer/papers/aaai/adam-agent.html(visited 1998).

S.Franklin,A.Graesser,Is it an Agent or just a Program?(它是代理还是程序?)A Taxonomy for Autonomous Agents(自控代理的分类),in:proceedings ofthe Third International Workshop on Agents Theories,Architectures,andLanguages(出处:关于代理理论、结构和语言的第三次国际专题讨论会的会议论文集),Springer-Verlag,1996,http://www.msci.memphis.edu/`Franklin/AgentProg.html(visited 1998).

B.Hayes-Roth,K.Pfleger,P.Lalanda,P.Morignot,M.Balabanovic,Adomain-specific Software Architecture for adaptive intelligent systems(自适应智能系统的特定域软件结构),IEEE Transactions on Software Engineering,April 1995(IEEE软件工程学报,1995年4月),pp.288-301.

Y,Shoham,Agent-oriented Programming(面向代理编程),ArtificialIntelligence(人工智能),Vol.60,No.1,pages 51-92,1993.

M.R.Genesereth,S.P.Ketchpel,Software Agents(软件代理),Communications of the ACM(ACM通信),Vol.No.7,July 1994,pp.48-53,147.

A.Cheyer,L.julia,Multimodal Maps:An Agent-based Approach(基于代理的方法),http://www.ai.sri.com/cheyer/papers/mmap/mmap.html,1996.

T.Khedro,M Genesereth,The federation for interoperable agent-basedconcurrent engineering systems(能互相操作的基于代理的并行工程系统的联盟).In Intemational Journal on Concurrent Environment,Research andApplications(出处:并行环境、研究和应用的国际定期刊物),Vol.2,pages125-131,1994.

P.Brazdil and S.Muggleton:“Learning to Relate Terms in Multiple AgentEnvironment(关于多代理环境的术语的学习)”,Proceedings of MachineLearning(出处:在机器学习的会议论文集)-EWSL-91,pp.424-439,Springer-Verlag,1991.

S.Cranefield,M.Purvis,An agent-based architecture for software toolcoordination(用于软件工具协调的代理结构),in Proceedings of the Workshopon Theoretical and practical Foundations of Intelligent Agent(出处:在关于智能代理的理论和实践基础的专题讨论论文集),Springer,1996.

T.Finin,J.Weber,G.Wiederhold,M.Geneserech,R.Fritzson,D.Mckay,J.McGuire,S.Shapiro,C.Beck,Specification of the KQML Agent-CommunicationLanguage(KQQML代理通信语言的规范),1993(以下称为“KQML1993”)http://www.cs.umbc.edu/kqml/kqmlspec/spec.html(visited 1998).

Yannis Labrou and Tim Finin,A Proposal for a new KQMLSpecification(新KQML规范的建议),TR CS-97-03,February 1997,ComputerScience and Electrical Engineering Department,University of MarylandBaltimore County(马里兰大学计算机科学和电气工程系),http://www.cs.umbc.edu/~jklabrou/publications/tr9703.pdf.

RR.Korfhage,Information Storage and Retrieval(信息存储和检索),JohnWiley&Sons,June 1997.

M.Mitchell.An Inttoduction to Genetic Algorithms(遗传算法导论).MITPress,1996.

D.C.Smith,A.Cypher,J.Spohrer,KidSim:Programming Agents without aprogramming language(不需要编程语言的编程代理),Communications of theACM(美国计算机学会通信),VOL.37,No.7,pages 55-67,1994.

3.相关技术的说明

大多数目前使用的人机接口是相当复杂和难以使用的。这经常是不断增长的希望接口能提供容易访问特征的原因。

用户经常有以下的关于当前接口的问题:

-在选择操作之前,用户必需考虑机器是否提供了全部适当的操作。因此,如果接口能够向用户提供反馈,则将是所希望的。

-访问用户已经知道的行动是困难的。因此,如果用户能够自由地表达他或她的需要而不限于由接口预置的一组规定的有限集合,将是所希望的情况。    

-用户必需想象为执行一定的机器域任务而继续进行的适当操作是什么。因此,如果接口能够通过它们在任何交互作用阶段可能有的许多选项来指导用户,将是所希望的情况。

使其特性适应用户特性的用户接口被称作自适应接口。根据用户的部分经验,这些交互作用软件系统提高了它们与用户交互(interact)的能力。用户的决定提供了一个真正的支持学习的训练数据源。在接口每次建议某些选择时,人们或者接受该建议或者拒绝该建议,无论该反馈是明示地还是只是反映在用户行为中。

以下的一般特点在用户接口中可能是希望的:

-自然表达:用户应能够尽可能自由地和自然地表达他或她的意图。

-最佳交互作用:交互作用应当被限制为用户对他或她下一步可以做什么或用户下一步打算什么迟疑不决的状态。这里要说明是,缺少来自系统的交互作用或反馈不是必然的理想情况。如果交互作用时常和不时常地出现在需要的地方,则被认为是最佳的。

-自适应性:自适应性可以是交互作用或应用的变化范围,但更重要的是,系统应当能够适应表达他或她的意图的用户方式。在这点上要考虑的两个主要问题是归纳和矛盾恢复(contradiction recovery)。

-归纳:最简单形式的自适应系统将只学习已经(隐性或显性)教导的例子。归纳出现在系统使用所学习的知识来解决被认为是相似的问题的时候。因此,归纳的成功和程度取决于相似性功能的精度和系统识别相似与不相似情况的阈值。

-矛盾:归纳化的系统可能过于一般化。基于归纳的系统反应的瞬间在某种意义上用户是不可预测的,因此系统陷入矛盾。该矛盾的解决是学习和自适应性处理的整体的一部分。

-变化和升级容易:系统设计者应当能够容易地升级或改变系统,使系统具有该系统对用户产生的适应性的最小折衷。甚至在运行时间(例如,飞行中(on the fly)),最好变化也应当是可能的。

已经安排各种尝试去减少菜单分级结构中的导航效果:

-对菜单项随机存取(例如,快捷键)。

-弹出菜单的指针设置策略对某些菜单项提供更快的存取,这些菜单项通常是最近或者最频繁使用的。    

-提供选择有效和适当项目方面的用户求助(例如,失效菜单项的灰影)。

-与先前选择的对象相应的操作提示(特定对象菜单或动态交换控制面板)

-与特定用户使用模式相应的菜单重组。

-交互作用的自动重复模式(例如,Eager系统,它是可以预测用户打算执行哪一个后续操作的依据实例编程的系统)。

当今的大多数人机接口是按标准序列或面向对象软件编程的。还存在另一种软件范例,不过迄今为止它还未能有效地用于人机接口。借助通常被称作基于代理的软件结构的这种范例,一个给定任务被分成几个子任务并被分配给系统的不同“代理”。“代理”是通信并行(conccurrent)模块,其每个控制一部分决策处理。如果代理能够学习,则把它们称作自适应代理。

某些使用基于代理的交互作用的情况的例子如下所述:

-代理可以被用来提供信息的定制显示。这些代理以对每个用户可以是专用的方式预处理数据和显示数据。

-代理充当老师或指导,用它们自己的知识补充用户的知识。这样,通过提供另一种观点和附加的相关信息来辅助完成当前任务。

代理可以用于信息的自适应搜索和检索。

在用户交互中使用代理的一个主要方法是必需在单个代理中集中大量的交互作用职责,从而回到一个中心化结构。然而,许多真实世界的问题最好使用一组合作智能系统来模拟。例如,我们的社会由许多交互作用实体组成。如果我们对我们社会的某些方面感兴趣,则希望以相同的方式构造我们的模型。作为另一个实例,由于数据经常在不同的物理位置产生,因此中心化方案经常是不适合的和不方便的。此外,采用在一个大的复杂的代理中插入大量的小的简单的代理的方案可以简化解决问题的处理。换句话说,代理集体地呈现展示自然发生(emergent)行为,全体代理的整体行为大于其各部分之和。

发明概述

概略地说本发明包括借助其每个具有它自己职责范围概念(view)的诸多代理的网络来处理主题消息的计算机实施方法。接收用户输入请求并且自己不具有相关解释(interpretation)策略的启动器(initiator)代理,询问其下行链路代理是否被询问的代理认为这种消息属于它职责范围内或这种消息的一部分。每个被询问的代理递归地确定它是否具备适用于该请求的特有的解释策略,如果不具备,则进一步询问其自己的再下行链路的邻近代理。再下面的代理最终响应这个进一步的询问,从而允许第一被询问代理响应于该启动器代理。这一过程递归调用最终确定经过网络从启动器代理到一个或多个分支(leaf)代理的一个路径或一组路径。然后把该请求向下发送给每个给定的路径,沿线的每个代理采取任何本地操作并把该消息传递给该路径上的下一个代理。如果发生矛盾,则网络通常能够根据预定的自动算法解决许多这样的矛盾。如果它不能自动地解泱一个矛盾,则它学习正确解释主题消息所需的新的解释策略。这种学习最好包括与用户的交互作用(但仅限于所需范围),并且最好把这种学习局限于尽可能接近网络中的正确分支代理的本地。尽管如此,该学习最好发生在该分支代理之前。

附图的简要说明

图1是实施本发明的软件可以被操作的计算机系统的简化符号的方框图;

图2是在图1的系统中使用的软件架构的整体方框图;

图3示出了本实施例中使用的代理的基本功能;

图4是图2中的面向代理交互作用单元内的代理社区的网络的部分示意图;

图5是主要对象分类的AGENT START(代理启动)方法的流程图;

图6是图5中的PROCESS MESSAGE(处理消息)步骤的流程图;

图7是响应ADVERTISE(通告)述行语的接收由主对象分类的代理执行的方法的流程图;

图8是代理响应UNADVERTISE(不通告)述行语的接收而使用的方法的流程图;

图9是响应IS-THIS-YOURS(这是你的吗?)述行语的接收由主要对象分类的一个代理执行的方法的流程图;

图10是当接收到三个可能的询问响应时由主要对象分类的一个代理执行的方法的流程图;

图11是图9、10、12、13中的PROCESS ANSWERS(处理回答)步骤的流程图细节;

图12是响应RESTORE(恢复)、THIS-IS-YOURS(这是你的)或COMMIT(提交)述行语的接收由主要对象分类的代理执行的方法的流程图;

图13是响应USER-REPONSE(用户答复)述行语的接收由主要对象分类的一个代理执行的方法的流程图;

图14是图13中的学习步骤的流程图细节;

图15是响应UNLEARN(不学习)述行语的接收由主要对象分类的一个代理执行的方法的流程图;

图16是响应DISSATISFIED(不满足)述行语的接收由主要对象分类的一个代理执行的方法的流程图;

图17是响应FORGET-PROBLEM(忘记问题)述行语的接收由主要对象分类的一个代理执行的方法的流程图;

图18是响应AGENT-SPECIFIC(代理专用)述行语的接收由主要对象分类的代理执行的方法的流程图;

图19是文本输入代理可以执行的代理专用通信功能的流程图;

图20、21、22和23是说明图4所示的网络响应某些典型的用户语音输入而执行的操作顺序的流程图;

图24是图20和23的网络中的代理决定多个下行链路(down chain)的消息主张者(claimant)而采用的步骤的细节;

图25是图2的面向代理解释单元内代理社区的另一个网络的部分示意图。

详细说明

本发明的方法和技术可以在几乎任何类型的计算机系统、微计算机或嵌入式处理器的软件中实施。作为图示说明,图1是实施本发明的软件可以被操作的一种类型的计算机系统的简化符号的方框图。图1的系统包括一个CPU110,它可以是例如可从英特尔公司(地址,Santa Clara,Califonia)得到的Pentium(奔腾)微处理器。CPU110连接CPU总线112,CPU总线112再与核心逻辑芯片组114和存储器阵列116连接。核心逻辑芯片组114也与存储器阵列116连接。核心逻辑芯片阵列114还连接ISA总线118和PCI总线120。标准视频适配器122与PCI(外围控制器接口)总线120相连接,并且驱动显示监视器124。键盘和鼠标126通过公知装置连接ISA(工业标准结构)总线118。ISA总线118还与标准声卡128相连接,声卡128与用于用户声音交互作用的麦克风130和扬声器132相连接。图1的系统还具有连接ISA总线118的串行口134,该串行口134具有连接机器138的串行控制输入的输出136,该机器138可以是例如家用娱乐系统。图1的系统还包括与ISA总线118相连接的硬盘驱动器140。当它与本发明相关时,图1的系统的目的是响应经显示监视器124、键盘及鼠标126、麦克风130和扬声器132发生的用户交互作用来控制家用娱乐系统138。

在操作中,当用户接口被启动时,硬盘140上存储的软件被带入存储器116,完全或按需要执行该系统的功能。

图2是图1的系统使用的软件结构的整体方框图。它包括从麦克风130接收输入的话音-文本变换器210,该变换器210将文本输出供应给面向代理解释单元212。语音-文本变换器210可以是传统的软件产品,比如龙系统公司的“自然说话”(地址:Newton,Massachuestts)。它通过标准Windows和Windows NT消息发送服务与面向代理解释单元212通信。面向代理解释单元212还具有一个输出,它通过标准文本-语音变换器213与扬声器连接。扬声器132用于向用户提供反馈。面向代理解释单元212还具有一个驱动家用娱乐系统138的控制输入的输出。它与显示器124和键盘/鼠标126通信,以作为与用户通信的替代物或备用装置。

单个代理的功能

图3示出了在本发明实施例中使用的这类代理的基本功能。具体地说,代理310包括三个主要部分:通信单元312,回报(rewards)单元314,和特殊处理单元316。在不是自适应(不学习)的实施例中,回报单元314可以省略。通信单元312和回报单元314(如果有的话)共同构成代理的“白箱”部分,而特殊处理单元316构成代理的“黑箱”部分。通信单元312和回报单元314被称作“白箱”,因为(下面将会明白)它们的内部功能对与代理310通信的其它代理是可视的。特殊处理单元316被称作“黑箱”,因为它的功能对系统的代理间(inter-agent)通信机构是不重要的,因此从该通信机构中隐藏起来。

通信单元312的主要职责是实施代理的通信功能,包括消息的解释和向其它代理发送消息。它包括从其它代理接受输入消息的输入单元318。这些消息可以为标准代理通信语言的扩展格式,例如KQML,KQML在上述的KQML1993基准中公开。这些扩展在下文中描述。在这里,术语“消息”尤其包括询问、命令和对询问的响应,等等。

输入单元318对输入消息执行某些初步处理,并把它传送给解释器320。解释器320判断输入消息是否在代理310的职责范围内。在这里,如果存在下列情况,消息被认为在给定代理的职责范围内:(a)该消息或其一部分是在给定代理的本地职责范围内(即,代理310的特殊处理单元316响应该消息或响应该消息的部分被指定的采取某些操作的职责),和/或(b)该消息或消息的部分是在给定代理的下行链路的职责范围内(即,代理310知道消息应该被发送到的一个或多个其它代理)。需要说明的是代理310能够把消息转送给一个以上的其它代理,从而建立代理间的竞争。

解释单元320涉及确定输入消息是否在代理310的职责范围内的解释策略单元322。解释策略单元322可以是例如一个包含代理310被指定去识别消息中的各种字或令牌(token)的表。该表指示,响应于包含代理已经识别的一个令牌的消息,代理310应该做什么。最好是,但并不必须这样,系统的设计者为每个代理把某些预定的策略集合编程为解释策略单元322,以便确保系统将从头开始即为功能性的。此外,对于是自适应的代理,解释策略单元还经过学习模块324接受来自回报单元314的解释策略。在系统复位的时刻,解释策略单元322的信息还原到基本硬编码的启动信息。因此,单元322中存储的解释策略包括一个预置知识库,以及学习知识库。在供不同用户使用的系统中,多个被学习的知识基于每个用户获得。对于先前请求处理中所接收的反馈,学习模块324在知识库项目(entry)中对矛盾解决负责。由于预计先前请求和先前请求在代理310中的最终处理还被存储在临时请求存储单元326中,因为预料会有它们的反馈。

解释单元320与地址簿328通信,该地址簿保持代理310已知有用的其它代理的地址表,或代理310已知具有处理代理310不能处理的某些输入的能力的其它代理的地址表。当代理310已经接收到一个它不知道如何处理(例如,对解释策略单元322中不存在的项目的询问)的消息,或者当代理310已经处理一条消息从而生成一条或多条新消息时,代理310可以把消息传送给其它代理。在这里所述的实施例中,每个代理具有一个地址,并且有一个特殊的名称服务器单元(未示出)。名称服务器单元在运行时向各个代理供应它们的专用地址,使新代理在运行时可以被引入该系统。在地址簿328中保持的地址表应当是动态的,因此是自适应的。它可以被限制在无用的和入侵的代理可以被排斥在外的意义上。它还可以包含关于把请求正常地发送给代理310的各代理(有时称之为“上游代理”)的信息(例如,性能或精度统计)。这样,地址簿328可以被认为是解释策略单元322的一个扩展,因此在某些实施例中,这两个单元被实施为一个单个模块。

地址簿328与有用的代理单元334通信,代理单元334存储有用代理的知识库,其方式与解释策略单元322存储解释器320的解释策略大致相同。除了由系统设计者编程的项目之外,有用代理单元334还包含学习单元332响应回报单元314的反馈而学习和存储的项目以及由于接收来自其它代理的注册消息而增加的项目。

代理310还包括输出单元330,它负责发送请求或使用地址簿328输出给其它代理。在一个实施例中,输出单元330根据已制订的用于解决或转发输入消息的解释来给其输出的某些消息添加置信度因子。如下文的详细描述,当代理310已经从响应于来自代理310的询问的竞争代理所作出的建议中被选择,可以使用置信度因子。

回报单元314处理两类反馈:输入和输出。代理310负责分发和传递已经反馈给它的回报。这种回报可以源于例如一个特殊目的代理(图3中未示出),它确定用户输入是否构成了关于对特定输入消息的系统响应的可接受性或不可接收性的反馈。当一个回报达到代理310时,回报单元314确定它自己应该得到输入的回报的什么部分和应当传递多少给其它代理。回报单元314响应这种回报把反馈供应给学习单元324,以便解释器320可以更新它的解释策略。回报单元314还向学习单元332提供响应这种回报的反馈,以协助地址簿328适应于其它代理的需要和规格。此外,在其特殊处理单元316可以受益于反馈的各代理中,这里的回报单元314也可以提供反馈。

经代理网络传递的回报在某些实施例中可以是用户状态的直接量化。然而在大多数实施例中,回报将构成由负责这些解释的代理作出的对用户操作的解释。

特殊处理单元316是代理310的部分,它执行代理310负责的除路由发送之外的本地工作。对于一个特定实施例的某些代理,特别是位于代理网络内部深处的某些代理,它们的任务主要是把请求传到适当的代理并且学习或解决可能在结合处发生的矛盾。对于这些代理,特殊处理单元316是非常简单的或完全省略。特殊处理单元316有时被称作“黑箱”,因为系统的设计者可以使用他或她认为适宜的任何方法,实施对给定代理的需求是专门(unique)的本地处理。对特殊处理单元316的唯一约束是最好将其限制在用于它与其它代理通信的通信单元312所提供的功能。

特殊处理单元316由与代理网络的外部进行交互的代理首先使用。负责用户I/O的代理是这种代理的例子。这些代理通常生成请求或在代理网络中启动回报传播,或简单地输出结果。

特殊处理单元316的另一个实例是已经被“代理化(agentified)”的现有传统的非面向代理程序。这些程序可以通过增加一个诸如312的通信单元(和任选的一个诸如314的回报单元)来“代理化”,它们作为调停现有程序与其它代理的转换器。转换器在例如上面应用的软件代理论文(Genesereth等人著)中公开。使用转换器来“代理化”现有程序的一个优点是转换器需要的不是先前存在的程序的知识,而是其通信性能。

代理化(agentification)(包装和改写)的其它方法在上面引入的软件代理论文(Genesereth等人著)中公开。

代理的互连

面向代理解释单元212(图2)包括大量的与图3的代理相似的代理,其每个具有一个职责范围。在一个实施例中,各代理按分层结构组织。顶层代理充当输入代理,它接收来自语音-文本变换器210的消息。消息按分层结构向下传播到(有希望的)合适的分支代理,沿线的每个代理执行自适应路径选择(routing)功能。

在另一个实施例中,面向代理解释单元212中的各代理的互连方式在某种程度上不满足分层结构的严格定义。也就是说,例如,有时候一个以上的中间代理可以把消息传送给单个分支代理。作为另一个实例,在该结构中更向下的代理可以把请求反向(向上)传送到是上级的其它代理(靠近输入代理)。在某些实施例中,代理的安排可以(例如)满足超结构(hyperstructure)的定义,如上面引入的Self-Organizing Symbiotic Agent(自组织共生代理)论文。通常,面向代理解释单元212中的各代理的安排可以被描述为一个网络。我们将会意识到超结构和分层结构是网络的特殊情形。此外,简单的代理链路(chain)是分层结构的特殊情形,单个代理是代理链路的特殊情形。所有这些排列和其它排列在这里被认为是网络类型。

网络中的不同代理在下述意义上被相互互连:各代理仅从网络中的其它代理(这里称作“上行链路”代理)的一个预定子集接收询问和命令,代理仅向网络中的代理(这里被称作“下行链路”代理)的另一个子集传送询问和命令。这两个子集在下述意义上是有适应性的:在线来的新的各个代理可以要求被加到它们的预期的上行链路邻居的下行链路代理表中(例如,通过ADVERTISE(通告)述行语),已经在子集中的代理可以请求被去除(例如,通过UNADVERTISE(不通告)述行语)。由于代理网络拓扑结构不限于任何方式,因此一个代理可以同时是另一个代理的上行链路和下行链路。

在特定实施例中,如果需要,则代理网络中的备代理可以组成代理社区。“社区(community)”含有一个或多个代理,它们具有相同的职责范围。在退化的情况下,一个代理可以自己构成只有一个代理的社区。各种实施例可以使用在多代理社区间进行通信的不同约定。例如,在一个实施例中,仅执行整个代理社区的询问,而不是执行社区内的任何单个代理的询问。响应可以来自社区中的单个代理,或者在一个实施例中,响应仅来自整个社区。因而,在这里,在一个适当的实施例中,是代理社区的部分的一个代理可以通过询问一个代理所属的社区被询问。也就是,这里对一组代理的询问被认为是包括在该组中的一个或多个代理的询问。需要说明的是,其它类型的代理组合(而不是社区)在一个给定实施例中是可能的。还需要说明的是,不是所有的具有相同职责范围的代理需要处于相同社区内。

当设计一个解释单元212中那样的网络时,整个软件可以被认为是一个社会,尽力满足一组询问。因此,输入请求由可以创建对其它代理的请求的各代理模块来传播、处理。系统的设计者将设计网络的整个职责的初始细目分类(breakdown),以便他们认为适当的方式分解该系统。代理的分层结构是可能的,并且代理可以被指定负责系统中的最精细处理。使每个代理保持其职责的简易并且被限制在它必需增强其学习能力的判断方面是可取的(但不是必需的)。然而,当白箱的开销应被考虑时,简易代理的过多增殖也不总是可取的。

在某些实施例中,代理可以在运行时用其它更完全的代理替换。该替换甚至可以是分解它们的前任的职责的新代理(子代理)的分层结构或网络。这一特点提供了增强的软件设计和估价。

最好的情况是在设计时清楚地定义每个代理的职责和操作。如上所述,根据代理的定义为每个代理预置白箱单元的许多方面也是所希望的。为了具有一个从最初开始的工作系统,设计者应当在设计时预先定义各代理间的基本通信链路(Link)。需要指出的是,这些通信可以在随时间改变,例如在引入新代理的情况下改变。因而,用这一方法论设计软件的一个重要方面将是确定参与的代理和它们的能力;即使在设计时它们将如何最终相互通信的具体细节也许是不知道的。

特殊目的代理

在特殊目的代理网络中,许多代理具有共同的结构并遵循相似的内部程序。然而,某些特殊目的代理是根据应用来使用的,例如,直接涉及发出请求给系统的代理,或把用户的操解释为不同的回报等级的代理。下面将说明这些特殊目的类型的代理。

输入代理。对系统的输入可以来自一个以上的源。在这种系统中,可以包含特殊目的输入代理之一或其网络,把来自不同源的输入合并成一个请求,和/或确定所有落入单个请求集(set)的命令。例如,如果用户的自然语言(“NL”)输入是:“Information on this”和随后把鼠标指在显示器的条目上,则输入代理也许执行把这两个输入合并为一个请求的功能。

交互输入还将受益于确定输入流结束的输入代理的使用。例如,在NL输入中,词组(例如,Do!或Please!),或相当长的停顿将确定流的结束。不同的策略将实时解释输入并把它转发给适当的代理。

反馈代理。任何自适应系统需要一个回报反馈,告诉自适应系统它的响应距最佳有多远。这一回报将明确地输入给系统,或依据输入响应由系统自己隐含地判断。在一个具有隐含回报的实施例中,反馈代理将负责输入行为的解释并把它转译成回报。使用的标准依赖于系统。例如,交互软件应用中,命令的重复、表示满意或不满意的注释、请求间的用户停顿或其它这样的输入将被转译成对不同输出的回报。

某些实施例具有一个以上的依赖于不同判断标准的反馈代理,并且设计建立回报的超结构或分层结构。

除了正常代理和特殊目的代理外,解释单元212还包括名称服务器单元,以使新代理动态引入到系统成为可能。每个新代理从该名称服务器得到其名称(或地址),所以冲突不会发生并且在整个系统中可以引用这些代理。对系统的输入请求或命令用一个请求标识符(request-id)标注(并且还用发出它们的用户的用户标识符(id)标注,因为解释是基于每个用户进行的),反馈给系统的回报并入该回报所属的请求标识符。

代理网络实施例

图4是面向代理解释单元212(图2)内的代理社区的网络的局部示意图。在图4中,每个椭圆代表一个代理社区(在本实施例中,其每个仅含有一个代理),或致动器。由于图4所示的所有代理社区恰好含有一个代理,因此在说明该图时,术语“代理”和“社区”被互换使用。互连图4所示网络中的代理的箭头指示发送询问和命令的方向。响应沿相反的方向传播。诸如注册和通告消息的其它类型消息的传送方向未在图4中示出。

在图4中,语音-文本转换器210的输入由文本代理410接收,而鼠标126的输入由鼠标代理412接收。代理410和412是特殊目的代理,其每个执行接收非代理I/O(输入/输出)的功能,将其转换成代理格式并供给输入调节器代理414。文本输入代理410还执行确定何时用户的请求或命令足够完全能使解释单元212进行解释的功能。文本输入代理410是经图4的网络传播某些命令的“发源地”。它响应从语音-文本转换器210接收的输入发出这种消息。文本输入和鼠标代理410和412还可以省略基本代理的更完善的通信功能中的许多功能,这是因为:它们不需要接收来自其它代理的输入,不需要学习,并且它们被预编程为把所有的输入消息发送给单个目的地代理。因此,例如文本输入和鼠标代理410和412可以省略输入单元318、回报单元314和图3所示的代理的所有学习能力。或者,可以使用广义的、全功能代理,尽管该代理的某些功能将永远不使用以及将增加某些其它功能。用于文本输入和鼠标代理410和412的非代理I/O由相应代理的特殊处理单元316(图3)执行。

(在这里,如果前任的信号或事件影响给定消息或事件,则给定消息、信号或事件对前任的消息、信号或事件发生“响应”。如果存在干预处理元素或时间周期,则给定消息、事件或信号仍然可以对前任信号或事件发生“响应”。如果干预处理元素合并一个以上的消息、信号或事件,则处理元素的输出被认为对该消息、信号或事件输入的每个发生“响应”。如果给定消息、信号或事件与前任消息、信号或事件相同,这只是给定消息、信号或事件仍然被认为对前任消息、信号或事件发生“响应”的退化情形)

输入调节器414是特殊目的代理,它执行合并文本输入代理410和鼠标代理412的输入的功能。它是TV代理418、VCR代理420和反馈代理422的上行链路。输入调节器还可以是对家用娱乐系统138的其它部分负责的其它代理或代理社区(未示出)的上行链路。当输入调节器代理制定询问时,它把该询问发送给它的下行链路邻居416、418、420和422。

图4还示出了询问或命令代理416、TV代理418和VCR代理420的上行链路和输入调节器代理414的下行链路。然而,它在图中用虚线示出,因为它仅用于说明对代理网络不同实施例的选项。实际上,它在此描述的实施例中不存在。在包含这样的一个代理的一个实施例中,它的目的是确定发自文本输入代理410的消息是反映用户关于家用娱乐系统138中的一个设置(例如,“电源仍然是接通的吗?”)还是命令(例如“开电视机!”)的当前状态的询问。询问或命令代理416的职责范围包含TV代理418的职责范围,因为代理416是TV代理418的上行链路。由于同样的原因,代理416的职责范围还包含VCR代理420的职责范围。在没有分离的询问和命令代理的一个实施例中,比如在此述的实施例中,识别来自用户命令的用户询问的功能可以被包含在文本输入代理410中。

反馈代理422是特殊目的代理,它确定输入消息是否载送用户关于对先前用户请求的系统响应的可接受性或不可接受性的明确或隐含判断。和询问或命令代理416的情况一样,反馈代理422用虚线示出,因为它仅仅是使该功能进入一个分离代理的选项。在本实施例中,采用用户不满意检测方式的反馈检测功能被包含在文本输入代理4l0中。

在具有分离反馈代理422的一个实施例中,该代理从不响应来自输入调节器414的询问,或如果它响应,则以极低优先级响应,使它从不被选择。而一旦反馈代理相信它已经接收来自用户的反馈时,它就把REWARD(回报)命令发送给输入调节器414,用于在网络的剩余部分传播。由反馈代理422发出的反馈命令载送“THIS IS YOURS(这是你的)”述行语,或者换句话说载送专用于回报传播的述行语。

VCR代理420是大量其它代理的上行链路,但图4中只示出了两个(424和426)。图4中示出VCR子网络的目的仅仅是强调输入调节器414的作判泱的职责包括把一个消息发送给对家用娱乐系统138的不同部件负责的几个子网络中的一个。这里不需要对VCR子网络作进一步描述。

TV代理418是电源代理428、声音代理430、视口代理432和频道代理434的上行链路。视口代理432又是放大代理436和移动代理438的上行链路。移动代理438是右代理440和左代理432的上行链路。电源、声音、放大、右、左、频道代理428、430、436、442和434分别是特殊目的TV致动器代理444的所有上行链路,致动器代理444的特殊处理单元316(图3)的功能是统一来自它的所有上行链路邻居的所有命令,并通过非代理I/O端口(图3)再经单串行端口134(图1)把它们供应给家用娱乐系统。电源、声音、放大、右、左和频道代理428、430、436、440、442和434还分别在它们的特殊处理单元316中存储它们负责的家用娱乐系统138的各种设置的当前值。例如,声音代理430包括一个存储当前音量设置的寄存器,使它能够适当地回答关于当前音量设置的用户询问。TV致动器444是非常退化(degenerate)的代理,省略了图3所示功能中的许多功能。例如,可以省略下列各项:学习单元324、解释策略单元332、有用代理单元334、临时请求存储单元326、学习单元332和回报单元314。一个不同的实施例也许保持一些或所有这些部件,只是简单地从不使用它们。另一方面,TV致动器444可以被看作(和编程为)一个非代理处理过程。

代理间的通信

面向代理解释单元212中的各个代理使用传统的被称作KIF(知识交换格式)的说明知识表达语言、传统的通信语言KQML(知识询问和操作语言)、定义各种域的词汇的形式本体论的数据库来接收和答复消息。KQML在上面引入的KQMLl993基准中公开。KQML是程序的标准语言,用来传达关于诸如询问、陈述、认为、需要、实现、预订和提供的信息的姿态。KQML消息(也称作“述行语”)包括大量的字段,它包括内容消息字段和指示推测接受者利用内容消息字段中的什么信息的字段。本实施例通过增加下述的大量的新述行语来扩展KQML。这些述行语都是普通的,因此预先实现在这些代理的白箱模块中。

登记

代理需要相互登记,以便能够把消息发送给另外一个。与其它的基于代理的系统不同,在本实施例中,所有代理不必被所有其它代理知道,并且可以使登记更加分散化和本地化。具体地说,每个代理仅需要向它的上行链路和下行链路邻居登记。每个代理一旦接收到登记消息,就把登记代理的姓名和地址添加到它的地址簿上。登记可以在运行时发生。登记述行语自身是通用的。

通告和不通告

代理通告它们的职责范围,以便从其它代理中取出请求。当代理接收到一个通告(ADVERTISE)消息时,它更新它的解释策略,以便把某些请求改发到通告代理。一旦接收到不通告(UNADVERTISE)消息,该消息就从解释策略中去除。通告消息指示通告代理属于的社区。例如,从视口代理432到TV代理418的通告消息可以说:“我要接收包含词语视口、放大、移动、右边或左边的所有输入消息”。如果接收到该消息的代理已经知道另一个代理要接收所有的相同消息,那么它将把最新通告的代理增加到已经包含先前代理的社区上。如果接收方代理在它的当前解释策略中不认识这样的社区,则可以添加它以作为一个新的社区。这允许一个以上的代理成为另一个代理的解释社区的成员。通告或不通告述行语本身是通用的。

THIS-IS-YOURS(这是你的)

当一个代理成功地解释消息时(即,代理已经作出消息的路由传送确定),该消息必需被传送给解释的社区内的一个代理。依据传送这一消息的述行语被称作THIS-IS-YOURS。接收的代理知道如果它不能解释该消息,那么矛盾点是它自己。例如,假定输入调节器代理414从文本输入代理410接收到“TV向右”,以及输入调节器414具有将含有词语“TV”的所有消息发送到TV社区418的解释策略。那么,输入调节器414将把该消息传送到那个社区中的一个代理。在本实例中,每一社区我们只有一个代理(即,每个社区只有一个代理),所以具有输入消息作为其内容的THIS-IS-YOURS述行语将被发送给TV代理418。

IS-THIS-YOURS?(这是你的吗?),IT-IS-MINE(它是我的),NOT-MINE(不是我的)和MAYBE-MINE(也许是我的)

如前所述,输入的解释分布在代理的网络上,所以很可能出现这些情况,其中代理不能直接解释消息,它将询问它所知的社区并等待它们的响应。如果代理本身不能解释接收的消息(即没有用于该消息的解释策略),则使用IS-THIS-YOURS述行语询问其每个下游社区。如果一个收到该述行语的代理有该消息的解释策略,该代理用IT-IS-MINE述行语进行响应。如果一消息(或其一部分)是处在一代理自己的本地职责范围或该代理知道该消息(或其一部分)是在该代理的下行链路邻居之一的职责范围内,该代理就会有用于该消息的解释策略。在这个意义上,术语“职责范围”是递归定义的。

如果接收IS-THIS-YOURS述行语的代理不具有用于该消息的解释策略,并且其自己的下游邻居(如有的话)也都没有这样的策略,则该代理用NOFMINE述行语作响应。如果接收IS-THIS-YOURS述行语的代理有不止一个以矛盾的方式要求该消息的进一步的下行链路代理,则该代理由MAYBE-MINE述行语响应。

提交(COMMIT)和不满意(DISSATISFIED)

这些述行语用来强迫系统解决由系统经历的矛盾。在自适应实施例中,矛盾在学习中扮演重要角色。查明对矛盾负责的代理和在那里解决它确保了代理网络中职责的正确分配。在本实施例中,矛盾在下述情形中发生:

1.当接收到THIS-IS-YOURS(这是你的)消息的一个代理自己不能解释它和所有它的正在被询问的社区用NOT-MINE(不是我的)消息响应时。

2.当接收到THIS-IS-YOURS消息的一个代理不能解释它和一个以上的它的正在被询问的社区用NOT-MINE(不是我的)消息以矛盾方式响应时。

3.当用户对系统的一个答复表示不满意时。

这些情形的前两个可以表示COMMIT(提交)述行语,而第三个表示DISSATISFIED(不满意)述行语。

如前所述,文本输入代理410的功能之一是确定它何时从用户接收到为了使系统尝试解释它的足够的输入消息。例如,文本输入代理410可以被编程,它根据当时情况,把输入消息和用户说完每个字之后的THIS-IS-YOURS述行语下发送给输入调节器代理414,直至该解释成功。通常,如果输入消息导致上述的矛盾情况(1)或(2)的任一个,那么在输入调节器代理414接收到来自所有它的下行链路邻居的答复之后该消息简单地消散。仅仅等候更多输入的系统不采取操作。由文本输入代理410向下传送的下一个消息比较长,它增加了用户的后续字,它有望能够进行解释。然而在某些时刻,用户可以暗示或表达系统响应迄今输入的一个愿望。在这种情况下,文本输入代理410根据当时情况把输入消息和COMMIT述行语向下发送给输入调节器代理414。需要说明的是在一个实施例中,COMMIT述行语被实现为具有COMMIT标记集的THIS-IS-YOURS述行语。

如果当COMMIT被发出时待泱矛盾是在输入调节器414上,则输入调节器414着手解泱该矛盾。任何预先定义的矛盾解决过程可以被编程到系统中。然而,如果它包含直接询问用户的步骤,最理想的情况是,宁可作为一个最后求助手段。例如,如果输入调节器414具有一个因为它的所有下行链路邻居都返回NOT-MINE而造成的矛盾,那么输入调节器414可以询问用户输入消息是否涉及TV或VCR功能。然后输入调节器根据用户的答复调整它的解释策略322。通过以这种方式联系用户,把交互作用和学习限定到矛盾点上。从而减少了不必要的交互作用,并且确保经代理网络正确分配学习。

输入调节器414解决它的矛盾后,它将消息与COMMIT述行语一起发送给它的已解决的下行链路邻居。如果输入调节器414不是矛盾点(即,输入调节器414已经有了对输入消息的解释),那么在这种情况中,输入调节器414将输入消息与COMMIT述行语一起发送给已解释的下行链路邻居。COMMIT述行语向下传播到该网络中的代理的一个链路,迫使具有矛盾的链路中的每个代理解决它的矛盾并把COMMIT述行语传送给该链路中的下一个代理。全部矛盾解决的处理可以在系统向用户请求一个判决中很好地解决几个用户交互。

输入调节器代理414中使用的实际矛盾解决过程在下文中结合图24作了更详细的说明。图4网络中的所有代理使用相同的矛盾解决过程,尽管在一个不同的实施例中,不同的代理可以使用不同的矛盾解决过程。由于该网络中的一个以上的代理必需能够询问用户,因此所有代理通过公共I/O致动器446路由传送这种询问,其中公共I/O致动器446控制I/O端口,通过该I/O端口进行这种用户交互。在一个实施例中,该用户交互通过键盘126和显示器124发生。在另一个实施例中,该用户交互作用通过家用娱乐系统138的部件发生。

DISSATISFIED述行语的使用,不是在系统为自己确定已经发生一个矛盾(上述的矛盾情形(1)和(2)时,而是在一个诸如用户的外部管理者通知系统一个矛盾已经发生(上述的矛盾情形(3))时。在这种情况下,系统内部没有待泱矛盾,而是已经响应用户的在前输入采取了某些操作。(由于此原因,检测用户不满意的代理一般在DISSATISFIED述行语前加上RESTORE述行语,以便取消(undo)大多数新近采取的操作。)由于系统不知道矛盾点在代理网络中的位置,因此它在该链路的每步(step)上询问用户直至到达一个分支代理。例如,如果输入调节器414(或一个适当实施例中的反馈代理422)在一个输入消息中确认用户不满意,例如呈现“错了!”的惊呼,则它向用户用户提出诸如“你是指TV还是VCR?”的问题。如果用户回答是“TV”,则输入调节器414学习到:具有导致用户不满意的输入消息的特征的消息属于TV代理418而不属于VCR代理420。然后输入调节器414用DISSATISFIED述行语把错误解释的消息向下传送给TV代理418。TV代理418然后询问用户“你是指电源、声音、视口还是频道吗?”。当用户答复时,TV代理418按照输入代理414的做法学习新的解释策略,并用DISSATISFIED述行语把错误解释的消息传送给指定的下行链路邻居。这一处理连续进行直至到达正确的分支代理并采取期望的行动。

各种代理响应DISSATISFIED述行语执行的用户交互可以通过I/O致动器446发生。该I/O致动器与响应COMMIT述行语解泱矛盾所使用的I/O致动器相同。

UNLEARN(不学习)

当用户在矛盾点通过与代理交互作用解决矛盾时,该代理学习该矛盾解决,以作为新的解释策略。例如,输入调节器代理414可以学会含有某些字的输入消息应当被传送给TV代理418。通常,学习一个新的解释策略的每个代理应当要求它所知道的所有代理来“不学习”该策略。一个UNLEARN述行语翻译为:“如果你正在解释该消息,并且该解释是这一消息属于我,那么不学习该解释策略”。不是所有的实施例都必需实行UNLEARN述行语,但是已实行的实施例最好能够将这些学习的策略限定在对每个策略最适合的代理内。这样的学习本地化有助于解释策略数据库保持最小,从而增加这种数据库被每个代理检索的速度,以及增加整个系统的响应度和性能。

LEARN(学习)

LEARN述行语由教导每个代理进行诸如“更多(more)”和“过于(too)”的全局抽象语(abstractions)的代理使用,它是常规的,但是包括在这里用于完备性。

FORGET-PROBLEM(忘记-问题)

通常,当一个代理接收到IS-THIS-YOURS?(这是你的吗?)询问,并且把它(该询问)传送给它的下行链路代理或者答复该询问的上行链路源时,该代理记住它已经处理了该消息。如前所述,该代理将这种问题与问题标识符一起存储在临时请求存储单元326(图3)中。这样,例如当该代理接收到随后的THIS-IS-YOURS(这是你的)消息时,代理不必重新描述它的解释或把该消息传播到已经拒绝该消息的所有权的下行链路邻居。

问题存储不同于已学习的解释策略,其中,已存储的问题和这种问题的任何解决不影响对用户所说的任何新消息的解释,即便新消息的文本与已存储的问题的文本相同。而对已存储的问题的所有引用靠问题标识符(ID)发生。FORGET-PROBLEM也不同于LEARN/UNLEARN,其中,LEARN/UNLEARN响应矛盾的解决而发生,而问题存储的发生则不考虑矛盾的解决,甚至不考虑矛盾的存在。此外,问题只是被临时地存储在临时请求存储单元326中。

在本实施例中,只有当引用问题标识符的FORGET-PROBLEM述行语的接收被删除时,代理才在本地删除已存储的问题,而且每当文本输入代理410发送一个新问题时,它都发送引用最新的问题标识符的FORGET-PROBLEM述行语。该策略被认为是管理每个代理的临时请求存储单元326数据库的容量的最好策略。在另一个实施例中,可以使用一个不同的策略,比如无论该代理何时接收到识别相同问题标识符的THIS-IS-YOURS、COMMIT或DISSATISFIED述行语就删除已存储的问题。

在某些情况中,用户将要求系统中止特定请求的处理。例如,当开始表述一个请求之后,用户可以停止并说:“擦掉”或“没关系”。如果文本输入代理410(或负责这一职责的某些其它代理)认可这样一个愿望,那么它立即从它的临时请求存储单元326中删除临时存储的问题,并随后将该问题标识符与FORGET-PROBLEM述行语传送给它的下行链路邻居。如果在这里也是这样,则该链路邻居的每个从它自己的临时请求存储单元326中删除被标识的问题,并把该问题标识符和FORGET-PROBLEM述行语传送给它的下行链路邻居,等等。在一个实施例中,如果问题标识符未存在于一个代理自己的临时请求存储单元326中,则该代理不向它的下行链路邻居传送FORGET-PROBLEM消息。在另一个实施例中,在其临时请求存储单元326中没有问题标识符的一个代理仅向它知道的先前已经接收到由该问题标识符指定的问题的它的那些下行链路邻居传送该消息。

面向对象代理网络的实现

面向代理解释单元212(图2)在一个实施例中使用诸如Java的面向对象编程语言来实现。定义主要对象分类包括对网络中大多数代理是共用的方法和数据结构。某些特殊目的代理,比如反馈代理422、询问或命令代理416、文本输入代理410和网络中的各种致动器(actuator)是已经从主对象分类中再细分类的对象,以便允许主对象分类的某些方法被替换、增加等等,使代理可以执行它的特殊目的的特殊功能。在一个实施例中,该网络中所有代理代表在不同的细分类中的对象,因为无论它们多么相似,它们总是有微小的差别。例如,每个代理被分别编程,根据它们在网络中由系统设计者预定的位置把REGISTER(登记)和ADVERTISE(通告)消息发送给不同的邻近代理。作为另一个实例,每个代理用它们自己的解释策略的默认设置来预见编程。作为再一个实施例,每个代理用它自己的“黑箱”过程编程,如有的话。在这个意义上,网络中的所有代理可以被认为是特殊目的代理。用于代理网络的其它面向对象和非面向对象的实现对读者来说也将是明显的。

图5是主对象分类的AGENT START(代理启动)方法的流程图,该方法每当代理进入在线时被执行。这里所含有的流程图应当被认为是符号而不是文字,它以被认为对读者非常有帮助的层面说明了一种实施情况。将被理解的是,一个实施例经常以不同于所示的顺序执行一个流程的各种步骤,或者在某些情况下与其它步骤并行执行。

参见图5,在步骤510,代理首先执行所需的任何初始化。在代理姓名不是被硬编码的实施例中,该步骤可以包括联系一个名称服务器以获得该代理的一个名称。

在步骤512,代理随后设置任何它的启动默认。在步骤514,该代理将它自己与将是它的上行链路和下行链路邻居的其它代理进行登记,这一切通告把REGISTER述行语与作为消息内容的代理名称发送给每个这样的邻居来完成。

在步骤S516,代理把它的能力通告给该代理要接收请求的其它代理。此事通过例如向所有的代理的预期的上行链路邻居发送一个消息与一个ADVERTISE述行语和一个字或令牌(token)的预编程表来完成。如果上行链路邻居随后接收到含有任何由通告代理所标识的字或令牌的输入消息,它将把该通告代理算作将把消息发送给那些代理的一个代理。

在步骤516之后,代理输入周期性地检查指向该代理的新事件的事件环。在步骤518,代理首先确定它是否仍然有效(alive)。如果不是,那么在步骤520中,该代理终止它的操作。如果该代理仍然有效,则在步骤521中,该代理执行任何代理特有的通信功能。在代理网络的诸多代理的主对象分类中,没有代理特有通信功能,因此步骤521不执行任何功能。如下面将看见的那样,不需要执行特殊通信功能的某些特殊目的代理,而在替代步骤521的一个程序中是这样做的。在步骤522中,代理确定它是否已经接收到任何输入消息。如果未收到,代理回到休眠状态并返回到步骤518。如果收到输入消息,则进入下文将详细说明的PROCESS MESSAGE(处理消息)步骤524。在该消息被处理之后,代理再次休眠和控制再次返回到步骤518。

图6是图5的PROCESS MESSAGE步骤524的流程图。在步骤610,代理根据它收到的消息的述行语执行合适的方法。这种述行语和它们对应于图6的步骤数目是:

ADVERTISE 700

UNADVERTISE 800

IS-THIS-YOURS?900

IT-IS-MINE 1010

NOT-MINE 1000

THIS-IS-YOURS 1200

COMMTI 1210

DISSATISTIED 1600

MAYBE-MINE 1020

UNLEARN 1500

FORGET-PROBLEM 1700

AGENT-SPECIFIC PERTORMATIVE 1800

USER-RESPONSE 1300

RESTORE 1320

代理也许能够处理其它述行语,但是为了清楚的目的,这些述行语在图6中省略。在执行专用于接收消息的述行语之后,PROCESS MESSAGE步骤524终止(步骤612)

图7是主对象分类的一个代理响应ADVERTISE述行语(步骤700)执行的方法的流程图。在步骤710,代理确定正被通告的社区是否已经被该代理知道。如果不知道,则在步骤712中,该代理在它的用于各代理的地址簿中建立一个新的社区,这些代理具有在接收的ADVERTISE消息中指定的特征。如果该通告的社区已经被该代理所知,则跳过步骤712。在步骤714,该通告代理在该代理的地址簿328中添加被指定的社区。

图8是代理响应UNADVERTISE述行语的接收而采用的方法的流程图。在步骤810,代理在接收的代理地址簿328中从它的社区中去除存储的未通告的代理。在步骤812,接收代理确定该社区是否还有一些代理。如果有,则UNADVERTISE方法终止。如果没有,那么在步骤816中,代理在终止该方法之前从地址簿328中删除该社区。

图9是由主对象分类的一个代理响应IS-THIS-YOURS?述行语(步骤900)所执行的方法的流程图。当代理接收到这样一个消息时,它首先检查它的临时请求存储单元326,以确定它是否已经事先解释了主题消息(步骤910)。如果不是,那么在步骤920,它执行该消息的解释。该解释包括两个检验:(1)代理首先确定该消息是否在它自己的本地职责范围内(例如,通过确定该输入消息是否含有与该代理需要采取本地行动相适应的某些字或令牌来实现),如果不是,(2)那么该代理确定它是否有已存储的用于输入消息的解释策略(例如,进一步的路由发送)。在步骤922,该解释是成功的,那么在步骤924中,代理把IT-IS-MINE返回到发送IS-THIS-YOURS?述行语(步骤924)的上行链路邻居。该方法随后终止(步骤926)。

在步骤922,确定在步骤920中执行的解释是否是不成功的(即,代理不声称该输入消息是它自己的并且没有用于该消息的解释策略),然后在步骤912中,代理检查它的地址簿328,以确定它是否有任何下行链路社区。如果没有,则把NOT-MINE返回到它的上行链路邻居(步骤913)。如果代理具有下行链路邻居,则在步骤928中,代理把该问题存储到它的临时请求存储单元326中。然后用同样的IS-THIS-YOURS?述行语询问它的所有下行链路代理(步骤930)。该方法随后终止(步骤926)。

返回到步骤910,如果IS-THIS-YOURS?述行语的消息主题先前已经被该代理解释,正如代理的临时请求存储单元326中指示的那样,则在步骤932中,代理从临时请求存储单元326得到该解释。临时请求存储单元326不但存储该代理发现的问题,而且还存储由该代理的所有下行链路邻居返回的答复。在步骤934,代理执行如下文结合图11所述的PROCESSANSWERS(处理回答)步骤。该程序随后结束(步骤926)。

图10是一个主对象分类的代理接收到对该代理先前发送给它的下行链路邻居的IS-THIS-YOURS?询问的三个可能的答复(NOT-MINE、IT-IS-MINE和MAYBE-MINE)的任何一个时,由该代理执行的方法的流程图。在步骤1022,代理首先把该答复(即,述行语)加到它先前接收关于该已存储的问题的任何答复上。这些答复被存储在该代理的临时请求存储单元326中。在步骤1024,该代理随后执行下文所述的PROCESS ANSWERS程序。然后该方法结束(1026)。

图11是分别相应于图9、10、12和13的步骤934、1024、1244和1316的PROCESS ANSWERS步骤1100的流程图。其中,PROCESS ANSWERS例程确定下行链路代理(如果有)适合接收该消息,等等。如果下行链路代理已经用主张(claim)具有对该代理是足够的相当质量等级的消息的一个答复来响应该下行链路代理的IS-THIS-YOURS?询问,则一个代理认为下行链路代理是合格的。也就是,主张一个消息的询问答复可以随着改变置信度的等级而作出,接收该答复的代理可以把它自己的质量标准应用于一个给定的答复,为它自己确定它是否认为发送那个答复的代理有资格接收该消息。每个响应代理可以通过使用例如答复消息中的置信度大小字段,把它的置信度大小发送给它的上游询问代理。此外,载送响应代理上或之外的一个矛盾的指示的答复(例如,在那里答复消息是MAYBE-MINE述行语,而不是IT-IS-MINE)还可以由其质量标准应用于该答复的询问代理所使用。换句话说,这里使用的术语“置信度大小”不但包括在一个实施例中也许被返回作为询问答复消息的部分的显性置信度值,而且还包括用其它方式(比如,引用该答复消息中使用的特定述行语)可以建议或指示的其它的答复质量的指示。

参见图11,在步骤1110中,PROCESS ANSWER(处理回答)例程通过打开使代理进入该例程的述行语(这里被称作进入述行语)来开始。如果述行语是IT-IS-MINE、MAYBE-MINE或NOT-MINE,则在步骤1116中,为当前代理建立的质量标准被应用于该答复。在本实施例中,步骤1116不采取任何行动。在另一个实施例中,步骤1116拒绝某些具有非常低质量等级的IT-IS-MINE和MAYBE-MINE答复,实质上是用NOT-MINE述行语替换它们。

在步骤2400,代理确定新答复是否产生了一个与任何先前接收的答复的矛盾。需要说明的是,即使两个下行链路代理都主张一个具有IT-IS-MINE述行语的消息,如果例如每个主张该消息的不同部分,也可以没有矛盾。例如,如果输入消息是“TV和VCR接通”,那么当TV代理和VCR代理都主张该消息时,则不会在输入调节器代理414中建立矛盾。这两个代理最终都必需接收该消息。

为了调节消息的多个非矛盾主张者,引入“焦点”概念。主张一个消息的所有权的每个代理用其IT-IS-MINE或MAYBE-MINE述行语,返回一个表示该消息的哪一部分或哪些部分造成该代理主张该消息的一个指示。造成代理主张该消息的该消息的特定部分或多个部分的指示被称作该主张的焦点。主张的焦点可以是或者消息的邻近部分或者消息的不邻近部分。如果消息实际上由两个或多个再下行链路代理主张,那么准备IT-IS-MINE或MAYBE-MINE答复的代理指定通过再下行链路代理主张的消息各部分的合并而给定的焦点。

步骤2400利用焦点以及下文中结合图24所述的其它技术,试图解决任何新矛盾。

在步骤1118,如果最新接收的答复是步骤1116和2400之后剩余的一个THIS-IS-MINE述行语,则代理增加这里被称作TheyKnowCount(它们知道计数)的一个变量。如果最新接收的答复(仍然)是MAYBE-MINE述行语,则代理增加TheyMayKnowCount(它们也许知道计数)变量。然后在步骤1112,确定所有被询问的社区是否已经应答。如果一个或多个社区还没有应答,则PROCESS ANSWERS例程结束(步骤1128),以等候进一步的答复。在本实施例中,一个代理认为它从给定社区中的一个代理接收的第一答复构成该社区的答复。以后来自该社区内的代理的答复,如有的话,也被忽略。在一个不同的实施例中,或者在相同实施例内的不同代理中,不同策略可以被利用来确定是否从一个下行链路代理或社区接收到足够的答复。

如果在步骤1112中所有的被询问社区现在已经应答,或如果造成该代理进入PROCESS ANSWES例程的述行语是COMMIT述行语,那么在步骤1120流程继续。

在步骤1120,如果TheyKnowCount等于零,那么在步骤1122中确定TheyMayKnowCount是否也等于零。如果是,那么在步骤1124,如果造成代理进入PROCESS ANSWERS例程的述行语不是COMMIT述行语(即,它是对IS-THIS-YOURS询问的答复或对THIS-IS-YOURS述行语的答复),则在步骤1126中,代理向发送该问题的上行链路邻居发送NOT-MINE述行语。该例程随后结束(步骤1128)。如果在步骤1124中造成代理进入PROCESS ANSWERS例程的述行语是COMMIT述行语,那么该代理有这样一种情况,其中该代理被要求确定它的已经拒绝当前消息的所有下行链路邻居中哪一个将仍然接收消息。所以,在步骤1130,代理要求用户解决该矛盾。然后该例程终止(步骤1128)通过步骤1300(图6)处理的USER RESPONSE(用户答复)述行语输入的用户答复。

如果TheyKnowCount等于零(步骤1120)而TheyMayKnowCount不等于零,则在步骤1132中确定输入述行语是否为COMMIT述行语。如果是,则在步骤1130中,代理再次要求用户解决起源于一个以上MAYBE-MINE询问答复的矛盾。然后该例程结束(步骤1128)。如果在步骤1132中,输入述行语不是COMMIT述行语,那么在步骤1134中,该代理把MAYBE-MINE返回它的上流询问代理。然后该例程结束(步骤1128)。

如果在步骤1120中TheyKnowCount被确定不等于零,则在步骤1136中确定TheyKnowCount是否等于1。如果是,则没有矛盾,因为正好只有一个下行链路邻居无条件地主张该主题消息。如果该主题消息载送IS-THIS-YOURS述行语(步骤1138),则在步骤1140中,代理把IT-IS-MINE返回给它的上行链路询问代理。然后,该例程结束(步骤1128)。如果在步骤1138,该消息载送某些非IS-THIS-YOURS述行语的东西,例如载送THIS-IS-YOURS述行语,那么在步骤1142中,该代理把该消息传送给已经主张该消息的所有它的下行链路邻居。然后,该例程序结束(步骤1128)。如果在步骤1136中,不止一个下行链路代理已经主张了具有IT-IS-MINE述行语的代理消息但该主张的焦点不重叠,则没有矛盾。该代理向上行链路询问代理发送IT-IS-MINE述行语(步骤1140),或者向所有主张的下行链路代理发送所存储的述行语(步骤1142),就好象只有一个下行链路代理主张具有IT-IS-MINE述行语的消息。

如果一个以上的下行链路代理已经主张具有足以满足本代理的质量等级的消息(TheyKnowCount大于1),并且主张的焦点重叠(步骤1136),那么指示一个矛盾。如上所述,控制转移到步骤1132。如果输入述行语是COMMIT述行语,则系统再次要求用户(步骤1130)解决该矛盾,随后该例程结束(步骤1128)。如果输入述行语不是COMMIT述行语,而且不是在此时解决该矛盾,则代理简单地把MAYBE-MINE述行语返回给IS-THIS-YOURS消息的上行链路的发送者(步骤1134)。然后,该例程结束(步骤1128)。代理不尝试解决该级上的矛盾,因为,例如该代理也许不在最后确定的任何最终消息路径中。

图12是主对象分类的一个代理响应RESTORE、THIS-IS-YOURS或COMMIT述行语的接收所执行的方法的流程图。如果输入消息的述行语是THIS-IS-YOURS或COMMIT,那么在步骤1222,代理根据特殊处理单元316中它的黑箱程序处理该消息。除了路由发送或学习外,这是代理的本地工作(如有)发生的步骤。如果输入消息的述行语是RESTORE,那么在步骤1224中,代理执行其黑箱RESTORE处理,取消它最近采取的无论什么样的行动。例如,如果用户表达取消最近行动的一个愿望,或如果用户对于对最近命令的系统答复表示不满意,则可以发出RESTOER(恢复)述行语。

在采取用户专用步骤1222或1224之后的所有情况中,进行图12剩余步骤所显示的白箱路由发送步骤。具体地说,在步骤1226,代理首先确定该输入消息是否被该代理已经在前解释过。这涉及检验临时请求存储单元326。如果没有,则在步骤1228中,代理确定它是否具有任何更远下行链路社区。如果没有,那么图12的程序结束(步骤1230)。该代理已经做它自己的工作,并且没有更进一步的下行链路代理,这样的下行链路代理也许有响应输入消息而执行的它们自己的工作。如果在步骤1228中,该代理被确定有下行链路社区,则在步骤1232中,代理试图解释该消息。如同步骤920(图9)中的情况一样,这一处理包括检验解释策略单元322以确定该输入消息是否适合任何预编程的或学习的解释策略的标准。然而,和步骤920不同的是,不需要识别要求当前代理执行本地工作的解释策略的步骤1232。在步骤1234中,如果该解释是成功的(即,该代理知道它的对接收消息感兴趣的下行链路代理的一个子集(合适的或不合适的)),则在步骤1236中,该代理向解释策略中表示的所有相关社区发送消息述行语(RESTORE、THIS-IS-YOURS或COMMIT)。然后结束图12的程序(步骤1230)。根据步骤1236接收述行语的每个代理通常将根据该相同图12程序来处理接收的述行语。

如果在步骤1234中,代理没有用于这一消息的解释策略,那么该代理在它的临时请求存储单元326中存储该问题(步骤1238)并用IS-THIS-YOURS述行语询问它的所有下行链路代理(步骤1240)。然后结束图12的处理过程(步骤1230)。任何答复将经历图6、10和11的程序。

返回到步骤1226,如果代理确定它先前已经解释了RESTORE、THIS-IS-YOURS或COMMIT述行语的消息主题,那么在步骤1242中,该代理检索它已经存储在它的临时请求存储单元326中的有关该问题的所有答案。在步骤1244中,代理执行上面结合图11所述的PROCESS ANSWERS例程。然后结束图12的程序(步骤1230)。

图13是由主对象分类的代理响应于USER-RESPONSE述行语执行的方法的流程图。这是I/O致动器446(图4)把用户答复反向发送给原始发出用户交互请求的代理(比如在步骤1130中(图11))的述行语。在图13中处理的给I/O传动器446的消息和它的答复包括对存储在代理的临时请求存储单元326中的问题标识符(ID)的引用。因而在步骤1320中,在接收到USER-RESPONSE述行语之后,代理从临时请求存储单元326中取出该问题。在步骤1312中,该代理以下文中结合图14所述的方式学习用户答复。在步骤1314中,该代理向当前代理的所有上行链路的代理发送UNLEARN述行语,以使当前代理中的学习本地化。

在步骤1316中,代理随后再次解释该问题并试图响应原始消息(如存储在临时请求存储单元326中的消息)。这一过程通过向图6的PROCESSMESSAGES例程再次提供该问题标识符来完成。然后结束该程序(步骤1318)。

图14是步骤1312的流程图细节(图13),示出了一个简单的学习技术。具体地说,在步骤1410中,代理只把该消息内容中包含的字或字组合或其它令牌添加到用于该代理的解释表322上。在其它实施例中,更加成熟的学习算法可以被编程。在步骤1412,结束该程序。

图15是由主对象分类的一个代理响应UNLEARN述行语执行的方法的流程图。UNLEARN述行语由例如执行诸如1314(图13)步骤的下行链路代理发送。如步骤1510所述,UNLEARN程序仅包含从当前代理的解释表322中消除消息内容的输入。当前代理不需要把UNLEARN述行语传送给它的上述链路代理。在步骤1512,结束该程序。

图16是由主对象分类的一个代理响应DISSATISFIED述行语的接收执行的方法的流程图。在步骤1608,代理首先从它存储的问题中检索当前的问题。在步骤1610,代理向用户请求关于该代理所知的哪个社区应对主题消息负责的反馈。在步骤1612,当用户响应后,代理通过在该代理的临时请求存储单元322中存储用户答复来学习新的解释策略。在步骤1613,如同步骤1314(图13),代理把UNLEARN述行语发送给该代理的所有上行链路邻居。在步骤1614,代理随后把DISSATISFIED述行语向下传送给该代理已经选择的相邻社区。在步骤1616接收该程序。

图17是由主对象分类的一个代理响应FORGET-PRCBLEM述行语的接收执行的方法的流程图。在步骤1710,代理从它的临时请求存储单元326中简单去除借助由该消息的内容指定的问题标识符而存储的问题。在步骤1712结束该程序。

图18是由主对象分类的一个代理响应AGENT-SPECIFIC述行语的接收执行的方法的流程图。尽管在理论上更喜欢黑箱/白箱的单纯实施,但在特殊应用中,它通常需要把命令发送给特定代理的特殊处理单元326,即使可能需要某些程序或该特殊处理单元316的内部数据的知识。在一个实施例中,系统允许这种通过AGENT-SPECFIC述行语的使用的命令。如图18所示,在步骤1810,代理的白箱部分仅把消息内容传送给代理的特殊处理单元316。然后结束该程序(步骤1812)。

如前所述,图4的代理网络包括某些代理,它们是扩展主对象分类的特殊对象分类中的诸多对象示例。实际上在一个实施例中,网络中的所有代理是扩展主对象分类的特殊对象分类中的诸多对象的示例。这些代理之一,特别是文本输入代理410(图4)将被描述。该代理不同于网络中的其它代理,这不仅是它的邻近代理的表不同,而且它在图5的代理专用(agent-specific)通信功能步骤521中所执行功能也不同。图19是由文本输入代理410执行的代理专用通信功能1900的流程图。

下面将回忆代理特殊通信功能在图5的事件环内发生的情况。无论文本输入代理410何时唤醒,在步骤1910中,首先确定这里是否有用户语音输入超时。特别是,代理确定预定的暂停周期是否已经期满,而没有任何进一步变化或来自用户的输入。如果是,那么在步骤1912中,文本输入代理410根据它当前情况用THIS-IS-YOURS述行语把输入消息发送给它的所有下行链路邻居。然后结束步骤1900(步骤1914)。将会发现,只是文本输入代理410的代理下行链路的输入调节器代理414将通过试图进行解释和询问它自己下行链路代理来响应该消息(如上所述)。

返回到图19,如果语音输入超时还未发生,但如果用户另外指示(例如,通过按输入键盘上按键)他或她希望按现实情况提交该消息(步骤1916),则在步骤1918中,文本输入代理410按现实情况用COMMIT述行语把该消息发送给它的所有下行链路代理。此外,唯一下行链路代理,输入调节器414按照前述方式响应。然后结束步骤1900(步骤1914)。

如果没有语音输入超时发生,并且未检测到用户提交指示,则在步骤1920中,文本输入代理410确定用户是否已经指示系统对用户的最近询问或命令的答复不满意。如果是,那么在步骤1922中,文本输入代理410用RESTORE述行语把先前的消息发送给它的下行链路代理,以使系统取消它的交互,然后在步骤1924中输入代理410再次用DISSATISFIED述行语把该在前消息发送给它的下行链路代理。然后结束步骤1900(步骤1914)。

如果用户输入超时已经发生,并且未检测到用户提交指示,以及用户不满意的指示未被显示,则在步骤1926中,文本输入代理410确定用户是否已经表示了一个取消以前操作的愿望。如果是,那么在步骤1928中,文本输入代理410用RESTORE述行语向它的下行链路代理发送在前消息,与步骤1922类似。然而,文本输入代理410不把DISSATISFIED述行语接在消息的后面。然后结束步骤1900(步骤1914)。

如果用户语音输入超时未发生,并且未检测到用户提交指示,也没有任何用户不满意已经被指示或消除命令已经被指示,则在步骤1930中,文本输入代理410确定用户是否已经请求重复先前操作。如果是,则在步骤1932中,文本输入代理410用THIS-IS-YOURS述行语把最后消息发送给它的下行链路代理,从而使系统重复最新行动。然后结束步骤1900(步骤1914)。

典型网络消息流

上述的大多数流程代表各代理的对象分类方法。作为一个整体的代理网络的全部功能由诸多代理间的通信和诸如上述的方法的性能(对每个代理内部而言)产生。为了更好地解释作为整体的代理网络的全部功能,图20、21、22和23是说明图4的网络响应某些典型用户语音输入而执行的操作的顺序的流程图。这些流程图不是用于覆盖所有可能的事件顺序,而是图示一些普通或典型顺序。

参见图20,流程图开始于文本输入代理410(图4)检测用户语音输入中的停顿(步骤2010)。在步骤2012中,根据步骤1912(图19),文本输入代理按当前情况用THIS-IS-YOURS述行语把输入消息发送给输入调节器代理414。在步骤2014,假定输入调节器代理414此前未发现问题(步骤1226,图12),并且具有下行链路社区(步骤1228,图12)。因此,输入调节器代理414试图进行解释(步骤1232,图12)。

在步骤2016,输入调节器代理414确定是否能解释输入消息(步骤1234,图12)。如果是,则在步骤2018中,向解释策略中表示的所有相关下行链路社区发送THIS-IS-YOURS(参见步骤1236,图12)。在步骤2020,接收这种THIS-IS-YOURS述行语的输入调节器代理414的每个代理下行链路递归地执行与这里所述的图20的那些步骤相似的步骤。

如果在步骤2016中,输入调节器代理没有用于该输入消息的解释策略,则在步骤2022中,输入调节器代理414把该问题存储在它的临时请求存储单元326(图3)中并用IS-THIS-YOURS?述行语询问它的所有下行链路代理(步骤1238和1240,图12)。

最后,输入调节器代理414的所有代理下行链路响应该询问(步骤2024)。每个响应通过实施图10和11的输入调节器代理的程序,这里包括质量标准的应用(标准1116),并试图自动地解决所有权的矛盾主张(步骤2400)。此时该矛盾的解决的尝试只按自动矛盾解决算法进行,如果自动过程失败,也不再要求用户解决矛盾。所有代理响应之后,在标准2026中,输入调节器代理414确定它是否从下行链路代理已经接收到一个或多个所有权的不矛盾主张(参见步骤1120和1136,图11)。如果它接收到,则流程返回到标准2018,在这里输入调节器代理把THIS-IS-YOURS发送给所有响应的下行链路邻居(图11的步骤1142)。每个下行链路邻居随后递归地执行与这里所述的图20的步骤相似的步骤。

如果在步骤2026中有多个矛盾的主张者,则在步骤2028中,输入调节器代理414仅把MAYBE-MINE(参见步骤1134,图11)返回给文本输入代理410。响应THIS-IS-YOURS述行语从一个代理接收NOT-MINE述行语表明矛盾已经发生。另一实施例可以使用用于此目的不同述行语,比如CONTRADICTION,当时在本实施例中MAYBY-MINE述行语是有效的,并且在响应THIS-IS-YOURS接收时没有其它含义。当MAYBE-MINE接收时,在步骤2034中,该程序结束而且输入消息被并全部忽略。

图21、22、和23描述了在输入调节器代理414把IS-THIS-YOURS?述行语发送给它的下行链路邻居(步骤2022)的时间与所有下行链路邻居响应(步骤2024)的时间之间发生在输入调节器代理414的各种代理下行链路中的处理。这些流程21-23不需要被限制为在单个代理内发生了什么。在步骤2110中,代理从它的上行链路发送者接收询问。最初,代理将是TV代理418或VCR代理420(图4),但是图21、22和23的流程图适于该网络中的任何下行链路代理。因而在这些流程图中主题代理被称作代理#i。

在步骤2112中,代理确定消息是否在它自己的本地职责范围内,或者它是否知道应当接收该消息的一个下行链路代理或多个代理。如果是,则控制转到下文所述的图22的流程上。如果代理不主张用于它自己的消息,并且没有适合输入消息的任何解释策略(编程或学习)存储,则在步骤2114中,代理确定它是否有任何下行链路社区。如果没有,则在步骤2116中,代理把NOT-MINE返回给它的上行链路发送者(参见图9的步骤913)。如果该代理没有下行链路社区,则在步骤2118中,它用IS-THIS-YOURS?述行语询问所有它的下行链路社区(图9的步骤930)。在步骤2120中,这些步骤循环地重复进行。最后,在步骤2122,代理#i从它的下行链路代理中接收所有的答复,把质量标准应用于每个答复并试图自动地解决所有权的矛盾主张(图11的步骤1116和2400)。在步骤2114,代理#i确定是否给它留下来自主张该消息或消息部分的一个或多个(它的)下行链路代理的非矛盾答复。如果是,则控制转到图22的流程图。如果不是,则控制转到图23的流程图。

返回到图22,在步骤2210中,因为代理#i已经收到来自一个或多个下行链路主张者的非矛盾答复,因此它把IT-IS-MINE返回给它的上行链路代理(图9,步骤940)。路径中往回直到发出IS-THIS-YOURS?询问的代理,在这种情况为输入调节器414,执行与这里所述的代理#i相似的操作。

输入调节器代理414发送它的询问,因为它已经在步骤2022中从它自己的上行链路邻居(文本输入代理410)收到THIS-IS-YOURS述行语,并且它没有可适用的解释策略。输入调节器代理414的所有代理下行链路已经响应后(步骤2024),如果所有权的所有矛盾主张是可自动解决的,则输入调节器代理把THIS-IS-YOURS述行语发送给所有相关下行链路社区(步骤2018)。被输入调节器代理414考虑的答复之一可以是来自引导代理#i的路径中的一个代理,矛盾的主张者的任何判断也许或也许不能以有利于那个路径的方式解决。该路径中的输入调节器代理414与代理#i之间的任何代理也可以有多个要解决的主张者,并且这些判断也许会或也许不会以有利于引导代理#i的路径来解决。因此,返回到图22,在步骤2212中,借助该处理的系统确定代理#i的所有矛盾发生上行链路是否以有利于到代理#i的路径而解决。如果不是,则在步骤2214中该消息将由网络中的某些其它代理处理(使用诸如开始于步骤2216的那些步骤)。如果是,则最终在步骤2216中,代理#i的上行链路邻居将最终把THIS-IS-YOURS述行语发送给代理#i。在步骤2218中,代理#i响应输入消息采取任何代理专用操作(如步骤1224或1222,图12),在步骤2220中,它把THIS-IS-YOURS传送给代理#i的其它相关代理下行链路。这是网络确定到正确的最终分支代理的正确路径的方式,然后使该路径中的每个代理执行它响应消息必需执行的任何代理专用功能。

如上所述,在步骤2124(图21)中,如果消息从代理#i的下行链路邻居接收,或者完全拒绝该消息或者以矛盾方式主张该消息,并且该矛盾是不可自动解决的,则控制转到图23的流程。在步骤2310中,如果所有的答复是NOT-MINE述行语,指示所有下行链路邻居已经拒绝该消息,则在步骤2312中,代理#i把NOT-MINE返回给它的上行链路发送者。因此代理#i将不在当前输入消息的任何最终选定路径上(除非用户经过使用DISSATISFIED明示地选择路径)。

如果在步骤2310中代理#i的被接收答复不全是NOT-MINE,则一个以上的代理#i邻居已经以矛盾方式主张该消息。根据代理#i使用的质量标准,这种主张也许包括收到的MAYBE-MINE述行语以及收到的IT-IS-MINE述行语,或者可以仅限制为收到的IT-IS-MINE述行语。在任何情况下,在步骤2314中已经从下行链路邻居接收所有权的矛盾主张的一个代理把MAYBE-MINE返回给它的上行链路发送者(参见步骤1134,图11)。代理#i不要求此时解决它的矛盾,部分原因是输入消息的最终选择路径可能恰好不包含代理#i。

最后,如同图22中的步骤2212的情况一样,系统确定代理#i是否在用于输入消息的操作路径内。所有的上行链路矛盾必需以有利于到代理#i的路径解决,以便代理#i最终接收该消息。如果不是这样(步骤2316),则在步骤2318中,该消息最终被其它代理处理。如果代理#被最终确定是在输入消息的路径内(或在输入消息的几个路径之一内),则在步骤2320中,它从其上行链路邻居接收具有THIS-IS-YOURS述行语的输入消息(步骤2320)。然而,由于该代理具有它不能通过它的自动算法解决的矛盾,因此该代理只能把MAYBE-MINE返回给它的上行链路发送者(步骤2319)。然后系统等候进一步的用户输入。

如果用户已经完成输入,并且系统仍然不采取行动,则用户可以发出COMMIT。假定COMMIT述行语最终到达代理#i(步骤2321)。代理#i采取任何需要的代理专用操作(步骤2322),并开始解决由对它的IS-THIS-YOURS?询问的答复所指示的矛盾,这里所述的答复是它先前在步骤2024中接收的。代理#i通过与用户的交互解决它的矛盾(步骤2324)。然后,在步骤2326中,它向它已解决的下行链路代理发送具有COMMIT述行语的消息。接收该消息的每个这样的下行链路代理响应该消息采取适当的操作,该操作在图22的流程图的实施的步骤2218上开始(如果代理已经从一个或多个它自己的下行链路主张邻居事先接收到非矛盾响应),或者在图23的流程的步骤2321上开始(如果代理已经从该消息的下行链路邻居事先接收到所有权的矛盾主张)。

图24是由网络中的代理为解泱一个消息的多个下行链路主张者所采取的自动步骤(图11中的步骤2400)的细节。不同的实施例可以采用解决这种矛盾的不同算法,并且一个实施例中的不同代理可以采用解决这种矛盾的不同算法。然而,理想的情况是所有这些算法不与用户进行交互,保留用户交互给以下的情况,其中用户表示系统响应的愿望,即使出现了系统不能自动地解决的矛盾(COMMIT述行语,图11步骤1130)。

在图24的算法中,首先假定来自已经用IS-THIS-YOURS?述行语询问的下行链路邻居的IT-IS-MINE和MAYBE-MINE答复上载送响应代理的优先级的一个指示。在本实施例中,代理优先级被编程为每个代理的对象分类。实例优先级在图4中示出,并且它可以被看作是,靠近(小的跳跃)IS-THIS-YOURS?询问的典型源发者的代理(输入调节器代理414)与距源发者代理更远的(大量跳跃)代理相比被指定了更高的优先级。如果一个代理因为它自己的解释策略主张一个消息,则它用IT-IS-MINE述行语把它自己的优先级等级传送给上行链路。如果一个代理仅因为它的下行链路之一已经主张了一个消息而主张该消息,则该代理向下行链路传送在下行链路代理的IT-IS-MINE(MAYBE-MINE)述行语中指定的优先级等级。这样,用询问答复返回的优先级等级与述行语(MAYBE-MINE或IT-IS-MINE)一同表示该代理认为它是该输入消息的所有者的置信度等级。这种置信度等级不仅可以在确定是否放弃所有权主张中(如前所述)由上行链路代理使用,而且也可以在图24的矛盾解泱步骤中使用。

具体地说,在步骤2406中,代理首先确定新近接收的所有权主张(IT-IS-MINE或MAYBE-MINE)的焦点是否与先前接收的任何主张的焦点重叠。如果不是,那么没有矛盾并且例程返回(步骤2408)。如果焦点重叠,则在步骤2410中,代理确定在它的所有主张该消息的下行链路邻居中是否有一个对于由具有重叠焦点的答复所指示的最高优先级等级的平局。如果没有,则它的答复具有最高优先级等级的那个代理获胜。较低优先级主张在代理临时请求存储单元326中被转换为NOT-MINE述行语和,如果那个主张已经事先造成TheyKnowCount(它们知道计数)或TheyMayKnowCount(它们可能知道计数)增加,则降低这样的计数(步骤2411)。如果矛盾解决,则例程返回(步骤2412)。

如果在具有重叠焦点的所有权主张中有一个优先级等级的平局,则判断在该算法的下一级上继续,确定具有重叠焦点的各个最高优先级主张者的哪一个已经收到一个最新的输入消息(步骤2414)。算法的这一级取决于观察到当用户作出一个关于家用娱乐系统138的一个部件的请求时,用户的下一个请求更可能会涉及同样的部件。例如,用户也许说“提高音量!”接着说“提高!”。例如,如果这些请求的第一个最终落实到图4中分支代理430(声音声音代理),则这些请求的第二个很可能也将被落实到该相同的代理,而不是图4的频道代理434。因此,返回到图24,如果在步骤2414中,代理确定在具有重叠焦点并具有最高优先级的两个或多个主张代理中,以崭新程度为基础,它们仍然是可辨别的,那么在步骤2415中,具有较弱的崭新程度的主张被变换为NOT-MINE,并且使TheyKnowCount(它们知道计数)或ThexMayKnowCount(它们可能知道计数)降低(如果适当的话)。在步骤2416中,由于矛盾已被解决,例程返回。

如果矛盾解决算法的前面两级都没有能够解决该矛盾,则在步骤2418中,没有解决矛盾,例程返回。如果将来,一个COMMIT述行语迫使代理解泱该矛盾,它将通过询问它的下行链路邻居的哪一个应该接收输入消息(参见步骤1130,图11)来进行这项工作。这可以通过例如向用户提供这种下行链路邻居的名称或说明来完成。在一个实施例中,代理提供它的所有下行链路邻居以供选择。在另一个实施例中,代理根据它的矛盾解决算法的一个或多个自动测试,比如步骤2410和2414的测试首先缩窄将向用户提供的选择的范围。在任何事件中,用户最终响应,并且系统根据图13的流程学习该响应。

实例

作为系统消息流的一个实例,假定文本输入代理410(图4)检测用户声音输入学习,“图象向右”。它用THIS-IS-YOURS述行语把该学习传送给输入调节器代理414。假定输入调节器代理代理414没有用于该消息的解释策略,它向TV代理418和VCR代理420发送IS-THIS-YOURS询问。VCR代理420也不能解释该消息,所以它向它的下行链路邻居424和426的每个发送IS-THIS-YOURS?述行语。在VCR子网络的代理中进行进一步通信之后,VCR代理420最终从它的所有下行链路邻居接收到NOT-MINE。因此,它对输入调节器代理代理414答复NOT-MINE。

同时,TV代理418具有用于输入消息的解释策略,即含有字“图象”的所有消息是在视口代理432的职责范围内。因此,它把IT-IS-MINE返回给输入调节器代理414。由于输入调节器代理414现在确实接收到一个主张该输入消息的答复(来自TV代理),因此它这次用THIS-IS-YOURS述行语把该消息返回给TV代理418。TV代理418执行对那个代理(在此情况中没有)的任何特殊的本地处理,并根据它的解释策略把THIS-IS-YOURS述行语传送给视口代理。视口代理432执行对那个代理的任何特殊的本地处理。然后,由于视口代理432具有下行链路邻居(分别是放大和移动代理436和438),并且它还不知道这种邻居的任何一个算法现在将接收该输入消息,因此它通过向它们发送IS-THIS-YOURS?消息来询问它的下行链路社区。然后,它等待直至它接收到来自它已经询问的所有代理的答复。

放大代理436本身不识别输入消息中的任何字并且没有任何下行链路社区(TV致动器不计数,因为它没有为它自己通告为具有任何特定职责范围),该放大代理以NOT-MINE响应。移动代理社区438识别属于右代理440的输入消息(因为在消息文本中呈现了字“右”),所以它通告把IT-IS-MINE消息返回给视口代理432来主张该消息。是当前询问的始发者的视口代理432目前已经确切地接收到一个TI-IS-MINE答复。因此它知道该消息属于移动代理(shifting agent)438。它这次用THIS-IS-YOURS述行语再次把该消息发送给移动代理438。该移动代理438将输入消息与它的问题的存储表(在临时请求存储单元326中)比较,并确定它先前已经发现了该问题以及该消息属于右代理440。这样移动代理438用THIS-IS-YOURS述行语把该输入消息再次发送给右代理440。右代理440在它的本地处理步骤1222(图12)指导TV代理使家用娱乐系统根据响应进行适当地调整。

假定移动代理438没有适用于词语“TV向右”的预先存在的解释策略。在这种情况下,一旦从视口代理接收到IS-THIS-YOURS?询问,它就响应NOT-MINE,而不是响应IT-IS-MINE。因此视口代理432从它的下行链路邻居接收到所有NOT-MINE,即使它已经从TV代理418接收到THIS-IS-YOURS述行语。该代理目前没有矛盾。因此该代理把MAYBE-MINE返回给TV代理418,并时该消息沿上行链路传送给文本输入代理,它在这里消散使系统只等待进一步的输入。

假定用户认可系统不打算执行预定的行动,并发出一个Commit(提交)指示。文本输入代理410认可此事并把COMMIT述行语发送给输入调节器代理414。输入调节器代理414已经发现该主题问题并事先确定该消息属于TV子网络。因此它用COMMIT述行语把该消息传送给TV代理18。TV代理418还确定它已经在以前发现了该主题问题,并预先确定该消息属于视口子网络。因此,它用COMMIT述行语把该消息传送给视口代理432。视口代理432也确定它以前已经发现了该主题问题,并进一步确定它具有一个矛盾。该COMMIT述行语要求视口代理432解决该矛盾。由于在该情况下,该矛盾是以从视口代理的下行链路社区接收NOT-MINE答复的形式存在的,因此它与用户进行交互,以解决该矛盾。例如,它询问用户“你的意思是放大还是移动?”。用户回答:“移动”。

一旦接收到用户的回答,视口代理就学习解释策略,比如(依赖于使用的特殊学习算法)含有字“右”的输入消息应当被发送给移动代理社区438。然后,它把UNLEARN述行语发送给视口代理432的每个上行链路邻居。只有视口代理432的上行链路的代理邻居是TV代理418,它目前没有用于含有单词“右”的消息的解释策略。因此TV代理418忽略UNLEARN消息。

在学习新的解释策略和发送UNLEARN消息之后,视口代理432用COMMIT述行语把该消息发送给移动代理438。移动代理438也有一个矛盾,即具有响应它的对主题问题在前询问,从它的两个下行链路邻居在前接收的NOT-MINE响应。因此,它与用户执行上述的交互并确定该消息应该发送给右代理440。移动代理438学习新的解释策略并把UNLEARN述行语发送给它的上行链路邻居,视口代理432。视口代理432响应该UNLEARN述行语消除它先前学习的解释策略,从而消除了网络中的学习冗余并使学习策略更加接近最终的恰当分支代理。

学习新的解释策略和发送UNLEARN消息之后,移动代理438最终用COMMIT述行语把该消息发送给右代理440。右代理440仅以它知道的方式作用于该消息(步骤1222,图12),通过把AGENT-SPECIFIC述行语发送给TV传动器444,使它将视口按一个增量右移。这样,网络按照适当的本地化方式学习:含有单词“图象”和“右”的消息应当经TV代理418发送给右代理440。

工业实用性

在传统的多代理系统中,学习问题已经在很大程度上被忽略。设计的将学习世界上任何事情的代理违反了分布式人工智能的基本原理。运也许是某些传统的系统为什么表现病态行为(它们学的越多,它们执行的就越慢)的一个原因。通过允许代理自动地或在用户控制下适应、精细和改进,可以建立一个整体明显大于它的各部分之和的完整系统。

在这里所述的实施例中,学习机器和多代理系统的结合具有这两者的益处。具有学习能力的多代理系统可以减少成本、时间和资源,并且以许多方式增加质量:

-易于编程

-易于维修

-宽广的应用范围

-高效率

-动作协调

另一方面,按多代理结构学习的机器变得更快和更强健。

这里所述的代理可按下列方式修改:

-系统在运行时接受新代理的能力。

-每个代理根据它接收的反馈调整它的行为的能力(即,学习)。

把代理的系统看作软件(被看作智能生物)可以导致结构和模块化方面非常不同于传统的多代理设计的设计。这里应注意该方法的某些益处。

-灵活性:没有有效输入消息的严格预定。

-并行性:代理的独立性质建立了一个潜在的并行设计方案,特别是,例如,不同代理可以在不同处理器上运行。

-多平台执行:代理可以在计算机网络(例如在互联网)上运行和通信。

-运行时增加新代理,从而增强软件的开发。

-由不同设计者增加软件:不同设计者可以引入在软件方面竞争的不同代理,使这种设计方法吸引商业应用。

-代理的可重复使用性。

-递增的设计和评估

-学习和智能:这里所述的学习的分布式特性建议强大的自适应软件设计,它潜在地突破了对简单学习模块的网络的应用。

-自然语言处理:该工作建议一种按分布和自适应方式处理自然语言的潜在的有力方法。

示例源代码

在附录Ⅰ中所述的是用于由图4网络中的代理使用的主对象分类的简单Java代码。附录Ⅱ包含阐明用于诸如代理410(图4)的文本输入代理的对象分类的Java代码。附录Ⅲ包含事先像输入调节器代理414(图4)的输入调节器代理的对象分类的Java代码。附录Ⅳ包含阐明菜单代理的对象分类的Java代码,该菜单代理实现一个诸如图4的代理444的TV致动器代理。

此外,图25举例说明了另一个控制家用娱乐系统138的代理网络程序。在图25中,深色的三维单元与传动器2510和菜单代理2520两者通信,而浅色阴影的三维单元与菜单代理2520通信而不与传动器2510通信。二维单元只是代理人式(proxy)代理,并且既不与致动器2510通信也不与菜单代理2520通信。它们执行解释功能,但只有它们执行的本地工作将通知执行相关工作的上行链路邻居。例如,处于DVD代理2524和VCR代理2526下行链路的播放代理2522解释用于DVD和VCR代理的“播放”命令。但是当播放代理2522最终接收到THIS-IS-YOURS述行语时,它的黑箱功能仅仅是请求DVD代理2524或VCR代理2526,视情况而定,以启动家用娱乐系统138的播放功能。通过AGENT-SPECIFIC PERFORMATIVE(代理专用述行语)进行通信的该请求允许所有DVD有关功能(和VCR有关功能)被控制和在单个代理(DVD代理2524或VCR代理2526)的黑箱中被保持。

图25的程序表2530仅仅是一个可从程序代理2532、去除代理2534和增加代理2536的黑箱软件中存取的小型数据库。程序表2530包含在特定的将来时间发生关于家用娱乐系统138的动作的用户编程请求。

本发明的优选实施例的上述说明已经为举例说明和公开的目的提供。它不是用来穷举或把本发明限制到公开的精确形式。很明显,许多改进和变化对本领域的普通技术人员将是显而易见的。例如,尽管这里描述的实施例被显示为按一个单处理器的计算机系统上运行的软件实施,但人们将会意识到,另一个实施例可以在多处理器系统上运行,或者可以经多计算机系统或诸多微计算机通信,例如通过TCP/IP(传输控制协议/互联网协议),来分布。此外,某些或所有代理可以以软件而不是硬件实施。其它的变化也将是显而易见的。作为另一个例子,尽管所述的实施例试图响应从下行链路代理接收的每个询问答复进行自动的矛盾解决,但另一个实施例可以收集所有答复,并仅在收到COMMIT述行语或其等同物时试图进行自动矛盾解决。这里所述的实施例是为了最好地解释本发明的原理和它的特殊应用选用的,从而使本领域的其它技术人员理解用于各实施例和具有对预期的特殊应用适合的各种改进的本发明。本发明的范围应由下面的权利要求和它们的等同物确定。

                              附录1

Sample Agent Class Prototvpe(代理分类原型样本) Copyright  1998 by Babak Hodjat and Dejima Corporation// Agent classpackage AAOSA3; import java.util.★; import java.awt.★; import java.beans.★ ; import borland.jbcl.control.★; public class Agent extends DecoratedFrame implementsAgentEventListener, Runnable{private Vector listeners=new Vector();//list of listenerspublic synchronized voidaddAgentEventListener(AgentEventListener aEventListener){listeners.addElement(aEventListener);}public synchronized voidremoveAgentEventListener(AgentEventListener aEventListener){listeners.removeElement(aEventListener);}protected void notifyAgentEventListeners(){ Vector1; AgentEvent e=new AgentEvent(this); synchronized(this)(1=(Vector)listeners.clone();} for(int i=0;i<1.size();i++){//deliver the event ((AgentEventListener)1.elementAt(i)).aEventFired(e); }} //deliver the agent event to registered listeners protected void notifyAgentEventListeners(AgentEvent e){ Vector1; synchronized(this){1=(Vector)listeners.clone();}for (int i=0;i<1.size();i++}{//deliver the event((AgentEventListener)l.elementAt (i)).aEventFired (e);}}publicvoid aEventFired(AgentEvent e){System.out.println("Agent: AgentEvent received by"+name+"from"+e.getSource()+"with args"+e.getArgObject()) ;}String name ; // the agent's namepublic String getName(){return name;}public void setName(String Name){String oldName=name ;name=Name;								changes.firePropertvChange("name",oldName,name);}private PropertyChangeSupport changes=newPropertyChangeSupport(this);public Agent(){name="Agent";}public Agent(String Name)(name=Name; }public void process(){};//perform the major processingfunctionpublic void reset(){};//reset the agent to a known statepublic void initialize(){};//initialize the agent forprocessing//required by Runnable interface and ThreadsThread runnit=new Thread();//start()ed in the process()methodboolean stopped=false;//control flagpublic void stop(){};//stop the agent threadpublic void run(){};//body of thread};//★★★★★★★★★★★★★★★★★★★★★★★★★//AAOSAAgent class prototype.//All AAosAagents should be completed extensions of this class.//AAOSAAgents don't send messages to themselves.package AAOSA3; import java.util.★; public class AAOSAAgent extends Agent implementsAAOSAConstants{static final String MY_NAME="AAOSAAgentl";static final int MY_PRIORITY=0;static final String MY_COMMUNITY="AAOSAAgent";/★The code in this comment should always begin any extensionsof this class.// registers should always be bothways (unless not using routingfeatures).// Note that the agent name should be replaced.private staticinstance=null;//singleton//in>Instance(){ if (instance==null){ instance=new("Input");>(); if(!instance.knownAgents.containsKey(((Agent)e.getSource()).getName())){								instance.knownAgents.put(((Agent)e.getSource()).getName(),e.getSource());((Agent)e.getSource()).addAgentEventListener(instance); instance.addAgentEventListener((Agent)e.getSource()); } else system.out.println(instance.name+"did notregister"+((Agent)e.getSource()).getName());★/iht priority;//AAOSA Agent's priority levelpublic AAOSAAgent(){super();name=MY_NAME;priority=MY_PRIORITY;}public AAOSAAgent(String Name}{super(Name);priority=MY_PRIORITY;};Public AAOSAAgent(String Name,iht Priority)(super(Name);priority=Priority;};Hashtable knownAgents=new Hashtable();//agent name iskey,agent object is valueHashtable communities=new Hashtable();//domain name iskey,vector of agent object is valueHashtable problems=new Hashtable();//request-content iskey,request message is valueHashtable learned=new Hashtable();//request-content iskey, request message is valueHashtable explanations=new Hashtable(); //agent name iskey,explanation of agent's domain is valueHashtable recency=new Hashtable();//agent name is key,recency of agent's delegation is valueAgentMessage msg;//current message being processedAgentMessage lastMessage=new AgentMessage();AgentStatus tempStatus;String processedItem;String AgentsWhoKnow=EMPTY_STRING;String AgentsWhoMayKnow=EMPTY_STRING;boolean onFocuses=false;String resultingFocus=EMPTY_STRING;public void reset(){ knownAgents=new Hashtable();//clear all agents commnunities=new Hashtable();//clear all communities problems=new Hashtahle();//clear all problems learned=new Hashtable();//clear all learned explanations=new Hashtable();//clear all explanations recency=new Hashtable();//clear all recencies!}public void process(){stopped=false;runnit=new Thread(this);runnit.start();}public void stop(){ stopped=true; runnit.stop();}//method of Runnable (Thread) interfacepublic void run(){								While(stopped==false){try{Thread.sleep((long)SLEEP_DURATION);}catch(InterruptedException e){//interrupted} // do any housekeeping nere!!! polling();}}public void aEventFired(AgentEvent e){Object arg=e.getArgObject();msg=(AgentMessage)arg ;route(msg);}public class Interpretation{ String result=EMPTY_STRING; String remainderRequest=EMPTY_STRING; String afterRequest=EMPTY_STRING; String beforeRequest=EMPTY_STRING; String newRequest=EMPTY_STRING; int index=NONE; public Interpretation(){ } public Interpretation(String Result, String RemainderRequest, String AfterRequest, String BeforeRequest, String NewRequest){ result=Result; remainderRequest=RemainderRequest; afterRequest=AfterRequest; beforeRequest=BeforeRequest; newRequest=NewRequest; }}public synchronized void d(String outString){System.out.println("DEBUG["+name+"]:"+outString);}public synchronized Interpretation interpretIt(String item,String processedItem, AgentMessage msg}{//This is an extremely simple minded, text-basedinterpretation policy.//It can be improved in extensions.int ti;boolean exactSearch;String tempMatch;Interpretation interpretation=new Interpretation();for (Enumeration learnedCateguries=learned. keys();learnedCateguries.hasMoreElements();){//check learnedinterpretationstempMatch=(String)learnedCateguries.nextElement();if (tempMatch.indexOf(EXACT_MATCH)==0){exactSearch=true;								interpretation.result=tempMatch.substring(EXACT_MATCH.length(),tempMatch.length());}else( exactSearch=false; interpretation.result=tempMatch;}if (((interpretation.index=processedItem.indexOf(interpretation.result))>NONE)&&((!exactSearch)||(((interpretation.index==0)||(processedItem.charAt(interpretation.index-1)==''))&&((interpretation.index +interpretation.result.length()==processedItem.length()) ||(processedItem.charAt(interpretation.index+interpretation.result.length())== ' ')))))( interpretation.afterRequest=processedItem.substring(interpretation.index+interpretation.result.length(),processedItem.length()); interpretation.beforeRequest=processedItem.substring(O,interpretation.index); interpretation.remainderRequest=interpretation.beforeRequest+interpretation.afterRequest; interpretation.newRequest=processedItem; interpretation.result=(String)learned.get(tempMatch); return interpretation; }}return null;}public class NumberInString{ iht theNumber=NONE; string reMainderString=EMPTY_STRING; iht index=NONE; iht MAX_NUMBERS=20; String[]numberStrings=new String[]("zero","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve";"thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","ninteen","twenty"};public NumberInString(){}public synchronized boolean find(String request){//★There are much better ways of doing this,I know!iht counter;int temp2;for(counter=MAX_NUMBRR_IN_REQUEST;counter>=-10;counter--) if((temp2=request.indexOf(Integer.toString(counter)))>NONE)if(((temp2==0)||(request.charAt(temp2-1)=''))&&((temp2+Integer.toString(counter).length()==request.length())||(request.charAt(temp2+Integer.toString(counter).length())==''))){								theNumber=counter;remainderstring=request.substring(0,temp2)+request.substring(temp2 +Integer.toString(theNumber).length(),request.length());index=temp2;return true;} //else return false; for (int numbers=MAX_NUMBERS;numbers>NONE);numbers--) if (((temp2=request.indexOf(numberStrings[numbers]))>NONE)&&((temp2==0}||(request.charAt(temp2-1)==''))&&((temp2+numberStrings[numbers].length()==request.length()}||(request.charAt(temp2+numberStrings[numbers].length()}==''))}{theNumber=numbers;remainderstring=request.substring(0,temp2)+request.substring(temp2+numberStrings[numbers].length(),request.length());index=temp2:return true; }  return false; } public synchronized boolean numberBetween(intlowerLimit,iht upperLimit){ return ((theNumber>=lowerLimit)&&(theNumber<=upperLimit}); } } public synchronized void sendMessage(Agent receiver,String performative,String content,String InReplyTo,String ReplyWith,String Language){tMessage msg=new AgentMessage(performative,content,InReplyTo,Language,Integer.toString(priority),receiver.name,ReplyWith,name); msg.display(); receiver.aEventFired(new AgentEvent{this,msg));}public synchronized void sendMessage(Agent receiver, String performative, String content, String InReplyTo, String ReplyWith, String Language, int MessagePriority){								 AgentMessaqe msg=new AgentMessage(performative. content, InReplyTo, Language,Integer.toString(MessagePriority), receiver.name, ReplyWith, name); msg.display(); receiver.aEventFired(new AgentEvent(this,msg));}public synchronized void sendMessage(Agent receiver, String performative, String content, String InReplyTo, String ReplyWith, String PriorityString, String Language) {AgentMessage msg=new AgentMessage(performative,content,InReplyTo,Language,PriorityString,receiver.name,ReplyWith,name); msg.display(); receiver.aEventFired(new AgentEvent(this, msg));}public synchronized long getCurrentTime(){Calendar rightNow=Calendar.getInstance();return(rightNow. get(Calendar.MINUTE)+rightNow.get(Calendar. HOUR_OF_DAY)★60+rightNow.get(Calendar. DAY_OF_YEAR)★1440);}public synchronized void initializations(){}public synchronized void startupDsfaults()()public synchronized void learn(AgentStatus status, StringwhichGroup, String whichAgent) {//This is an extremely simpleminded,text-based learningAlgorithm.//It can be improved in extensions. if(learned.containsKey(status.message.content.toLowerCase().trim()))//resolve contradiction (brutally!)learned.remove(status.message.content.toLowerCase().trim()); else if (learned.containsKey(EXACT_MATCH +status.message.content.toLowerCase().trim()))learned.remove(EXACTMATCH+status.message.content.toLowerCase().trim()); learned.put(EXACT_MATCH +status.message.content.toLowerCase().trim(),whichGroup.toLowerCase().trim());}								public synchronized void unlearn(String item) {//This is an extremely simple minded, text-based un-learningAlgorithm.//It can be improved in extensions. learned. remove (EXACT_MATCH+item.toLowerCase().trim());}public synchronized void polling(){//Will be executed everytime the agent comes alive.}public synchronized void processOtherMessages(AgentMessagemsg)(//for instance commitment replies.}public synchronized String processIt(String item){//This is an extremely simple minded,text-based process.//It can be improved in extensions. return item.toLowerCase().trim();}public synchronized String unProcessIt(String item){//This is an extremely simple minded,text-based unprocess.//It can be improved in extensions. return item.toLowerCase().trim();}public synchronized String toWhom(String item,StringprocessedItem,String whichGroup){ return null;}public synchronized boolean tagged(String item,String symbol,String Name){return(item.indexOf(symbol+Name+symbol)!=NONE};}public synchronized String tag(String item, String delimiter){return delimiter+item+delimiter;} public synchronizedvoid perform(Agent Message msg, Agentsender, boolean optimise){ int index; Agent agent=null; String whichAgent; String item=msg.content ; if ((msg.performative.equals(THIS_IS_YOURS))||(msg.performative.equals(DISSATISFIED)))processedItem=processIt(item);//Normally should notchange item. else if (msg.performative.equals(RESTORE))processedItem=unProcessIt(item);else processedItem=item.toLowerCase().trim();Interpretation interpretation=interpretIt(item,processedItem,msg);								 // If I don't have any communities under me I should returnNOT-MINE if (communities.size()==0) {if (msg.performative.equals(IS_THIS_YOURS))if (interpretation==null)sendMessage(sender,NOT_MINE,processedItem,msg.inReplyTo,msg.replyWith,msg.content);else (msg.language = interpretation.remainderRequest;sendMessage( sender, IT_IS_MINE, processedItem,msg.inReplyTo, msg.replyWith, msg.language);}return; } tempStatus=new AgentStatus(new AgentMessage(msg),EMPTY_STRING,new AgentMessage(lastMessage),O,EMPTY_STRING,EMPTY_STRING,EMPTY_STRING);while (interpretation!=null)(msg.language=interpretation.remainderRequest;Vector agents=(Vector)communities.get(interpretation.result); if ((whichAgent=toWhom(item,processedItem,interpretation.result))==null) {int num=agents.size() ;for(index=O;index<num;index++)(agent={Agent)agents.elementAt(index);//Firstagent?if(tagged(tempStatus.interpretations,IT_IS_MINE,agent.name))interpretation=null;else tempStatus.interpretations=tempStatus.interpretations+tag(agent.name,IT_IS_MINE)+interpretation.remainderRequest+NUMBER_DELIMITER;} } else if (tagged(tempstatus.interpretations, IT IS MINE,whichAgent))interpretation=null;else tempStatus.interpretations=tempStatus.interpretations+tag(whichAgent,IT_IS_MINE}+interpretation.remainderRequest+NUMBER_DELIMITER; if (interpretation!=null)( if (!communities.containsKey(interpretation.result))System.out.println("WARNING!["+name+"]:StrangeInterpretation for"+msg.content+""+interpretation.result+":"+learned+"\n");interpretation = interpretIt(item,interpretation. remainderRequest,msg); } } if (!problems.containsKey(msg.replyWith))problems.put(msg.replyWith, tempStatus} ; if (tagged(msg.inReplyTo,EMPTY_STRING, COMMIT)) sendMessage(agent,THIS_IS_YOURS,msg.content,msg.inReplyTo+tag(name,THIS_IS_YOURS),msg.replyWith,msg.language); else if (tagged(msg.inReplyTo, EMPTY_STRING,DISSATISFIED))								 sendMessage(agent,DISSATISFIED, msg.content,msg.inReplyTo+tag(name,THIS_IS_YOURS),msg.replywith,msg.language); else for (Enumeration agents=knownAgents.elements();agents.hasMoreElements(); ){ agent=(Agent)agents.nextElement(); if ((!agent.name.equals(sender.name))&&(!getCommunity(agent.name.toLowerCase().trim()).equals(EMPTY_STRING)))sendMessage(agent,IS_THIS_YOURS,msg.content,msg.inReplyTo+tag(name,IS_THIS_YOURS),msg.replyWith,msg.language); } if (tagged(msg.inReplyTo,EMPTY_STRING,COMMIT))( Enumeration childAgenUs=knownAgents.elements();//clean-up (only for agents that are not involved) Agent tempAgent; for (index=1; childAgents.hasMoreElements();index++){ tempAgent=(Agent)childAgents.nextElement(); if ((tempStatus!=null)&&//if it has been a problemfor this agent(!tempAgent.name.equals(sender.name)) &&(!getCommunity(tempAgent.name.toLowerCase().trim()).equals(EMPTy_STRING)) &&(!tempAgent.name.equals(agent.name)))//Tell all yourchildren to remove this from their problems.sendMessage(tempAgent,FORGET_PROBLEM,msg.content,EMPTY_STRING,msg.replyWith,msg.language); } }}public synchronized String getCommunity(String targetName) {String temp;int num;int ind;Agent agent;Vector agents; for (Enumeration cat=communities.keys();cat.hasMoreElements();){ temp=(String)cat.nextElement(); agents=(Vector)communities.get(temp); num=agents.size(); for (ind=0;ind<num;ind++){ agent=(Agent)agents.elementAt(ind); if (agent.name.toLowerCase().trim().equals(targetName))return temp; } } return EMPTY_STRING;}public synchronized String unexplain(String targetName)(String temp; for (Enumeration cat=explanations.keys();cat.hasMoreElements();){ temp=(String)cat.nextElement();								 if(targetName.equals((String)explanations.get(temp)))return temp; } return targetName;}public synchronized String makeQuestionString(AgentStatustempStatus, Agent sender){ int index; Agent agent; Enumeration agents = knownAgents.elements(); String question = EMPTY_STRING; if ((tempStatus.notMineAgentList.indexOf(IT_IS_MINE)>NONE)}{(tempStatus.notMineAgentList.indexOf(MAYBE_MINE)>NONE)){ for (index=1;agents.hasMoreElements();index++){ agent=(Agent)agents.nextElement(); if ((!agent.name.equals(sender.name))&&(!getCommunity(agent.name.toLowerCase().trim()).equals(EMPTY_STRINS))&&(((tempStatus.notMineAgentList.indexOf(tag(agent.name,IT_IS_MINE))>NONE))||((tempStatus.notMineAgentList.indexOf(tag(agent.name,MAYBE_MINE))>NONE)) || (tempStatus.notMineAgentList.indexOf(agent.name)<O))){ String temp=(String)explanations.get(getCommunity(agent.name.toLowerCase().trim()));if (question.indexOf(temp)<0)question=question+temp+OPTION_SEPARATOR; } } } else { for(index=l;agents.hasMoreElements();index++)( agent=(Agent)agents.nextElement(); if ((!agent.name.equals(sender.name))&&(!getCommunity(agent.name.toLowerCase().trim()).equals(EMPTY_STRING))&&(tempStatus.notMineAgentList.indexOf(tag(agent.name,COMMIT))==NONE)&&(tempStatus.notMineAgentList.indexOf(tag(agent.name,NOT_MINE))==NONE)){String temp=(String)explanations.get(getCommunity(agent.name.toLowerCase().trim()));if (question.indexOf(temp)<O) question=question+temp+OPTION_SEPARATOR; } } } if (question.length()==0){								agents=knownAgents.elements();for (index=1;agents.hasMoreElements();index++){agent=(Agent)agents.nextElement();if ((!agent.name.equals(sender.name))&&(!getCommunity(agent.name.toLowerCase().trim()).equals(EMPTY_STRING))&&(tempStatus.notMineAgentList.indexOf(tag(agent.name.toLowerCase().trim(),CO,IT))<0)){String temp=(String)explanations.get(getCommunity(agent.name.toLowerCase().trim()));if ((temp!=null)&&((question.iength()==O)||(question.indexOf(temp)==NONE))) question=question+temp+OPTION_SEPARATOR; } }}return question+IGNORE_OPTION+OPTION_SEPARATOR;}public synchronized boolean sendThemAll(Agent sender,AgentStatus tempStatus){ int index; boolean result=false; Agent agent; Enumeration agents=knownAgents.elements(); String question=EMPTY_STRING; if (!onFocuses)return false; for (index=1;agents.hasMoreElements();index++)( agent=(Agent)agents.nextElement(); if ((!agent.name.equals(sender.name))&&(!getCommunity(agent.name.toLowerCase().trim()).equals(EMPTY_STRING))&&(((tempStatus.notMineAgentList.indexOf(tag(agent.name,IT_IS_MINE))>NONE)&&(priorityMatches(tempStatus,agent.name,IT_IS_MINE)))||((tempStatus.notMineAgentList.indexOf(tag(agent.name,MAYBE_MINE))>NONE)&&(priorityMatches(tempStatus,agent.name,MAYBE_MINE)))||(tempStatus.notMineAgentList.indexOf(agent.name)==NONE))) {sendMessage(agent,THIS_IS_YOURS,msg.content,msg.inReplyTo + tag(name,THIS_IS_YOURSl,msg.replyWith,msg.language);result=true; } } return result;}public synchronized String tweekPriority(int priority){return Integer.toString(priority);}								public synchronized boolean onlyOne(){return false;}public synchronized boolean onFocus(String AgentsWhoKnow)(//★This should be selective. if (AgentsWhoKnow.equals(EMPTY_STRING))return false; Agent agent; Enumeration agents=knownAgents.elements(); String question=EMPTY_STRING; String delim=IT_IS_MINE; resultingFocus=tempStatus.maxLanguage; int indx; boolean IDidit=false; for (indx=1;agents.hasMoreElements();indx++)( agent=(Agent)agents.nextElement(); String theName = agent.name; if (tagged(AgentsWhoKnow,IT_IS_MINE,theName))( int index=tempStatus.notMineAgentList.indexOf(tag(theName,delim))+theName.length()+delim.length()+1;String prior =tempstatus.notMineAgentList.substring(index,tempStatus.notMineAgentList.indexOf(NUMBER_DELIMITER,index));iht index2=index+prior.length();Strinq requestFocus=focus(tempStatus,theName,delim);if((tempStatus.notMineAgentList.indexOf(tag(requestFocus,NUMBER_DELIMITER))==index2) && (checkFocuses(tempStatus,theName,delim,prior))) IDidit=true; resultingFocus=merge(msg.content,resultingFocus,requestFocus);} } return IDidit;} public synchronized void processAnswers(Agent sender,AgentStatus tempStatus,AgentMessage msg){ String tempName; String sendItTo; tempStatus.message.language=msg.language; tempStatus.message.content=msg.content; problems.remove(msg.replyWith); problems.put(msg.replyWith,tempStatus); Agent agent; Enumeration agents=knownAgents.elements(); int TheyKnowCount=0; iht TheyMayKnowCount=0; int index; AgentsWhoKnow=EMPTY_STRING; AgentsWhoMayKnow=EMPTY_STRING; for (index=1;agents.hasMoreElements();index++){ agent=(Agent)agents.nextElement(); if ((!tagged(tempStatus.message.inReplyTo,IS_THIS_YOURS,agent.name))&&(!tagged(tempStatus.message.inReplyTo,THIS_IS_YOURS,agent.name))&&								(!tagged(tempStatus.message.inReplyTo,RESTORE,agent.name)) &&(!getCommunity(agent.name.toLowerCase().trim()).equals(EMPTY_STRINS))) if ((!tagged(msg.inReplyTo,EMPTY_STRING,COMMIT))&&(!tagged(tempStatus.notMineAgentList,NOT_MINE,agent.name)) &&(!tagged(tempStatus.notMineAgentList,MAYBE_MINE,agent.name)) &&(!tagged(tempStatus.notMineAgentList,IT_IS_MINE,agent.name))) return;else if ((tagged(tempStatus.notMineAgentList,IT_IS_MINE,agent.name)) &&(priorityMatches(tempStatus,agent.name,IT_IS_MINE))){TheyKnowCount++;AgentsWhoKnow=AgentsWhoKnow+tag(agent.name,IT_IS_MINE); } else if((!agent.name.equals(tempStatus.message.sender)) && (!tagged(tempStatus.notMineAgentList,NOT_MINE, agent.name)) && (!tagged(tempStatus.notMineAgentList,IT_IS_MINE, agent.name)) && ((!tagged(tempStatus.notMineAgentList, MAYBE_MINE, agent.name))|| (priorityMatches(tempStatus, agent.name, MAYBE_MINE)))){TheyMayKnowCount++;AgentsWhoMayKnow=AgentsWhoMayKnow+tag(agent.name,IT_IS_MINE}; }}//d("tkc:"+TheyKnowCount+"tmkc:"+TheyMayKnowCount+tempStatus.notMineAgentList+":"+tempStatus.message.performative+":"+msg.inReplyTo+":"+recency); onFocuses=onFocus(AgentsWhoKnow); tempStatus.processed=true; if {((TheyKnowCount==1) && (TheyMayKnowCount==0)) }| ((TheyKnowCount==0) && (TheyMayKnowCount==1))) { if (TheyKnowCount==1)sendItTo=AgentsWhoKnow.substring(1,AgentsWhoKnow.length()-1); else sendItTo=AgentsWhoMayKnow.substring(1,AgentsWhoMayKnow.length()-1);if ((!tagged(msg.inReplyTo, EMPTY_STRING,COMMIT)) &&(tempStatus.message.performative.equals(IS_THIS_YOURS)))(//Oneagent knows!agent=(Agent)knownAgents.get(tempStatus.message.sender);problems.remove(msg.replyWith);problems.put(msg.replyWith,tempStatus);int tt;if (TheyKnowCount==1){String tempFocus=focus(tempStatus,sendItTo,IT_IS_MINE);								sendMessage(agent,IT_IS_MINE,msg.content,msg.inReplyTo,msg.replyWith,tweekPriority(tempStatus.maxPriority),tempFocus);} else {String tempFocus=focus(tempStatus,sendItTo,MAYBE_MINE);sendMessage(agent,MAYBE_MINE,msg.content,msg.inReplyTo,msg.replyWith,tweekPriority(tempStatus.maxPriority),tempFocus);}} else if ((tagged(msg.inReplyTo,EMPTY_STRING,COMMIT))||(tempStatus.message.performative.equals(THIS IS YOURS))){ if (tagged(msg.inReplyTo,EMPTY_STRING,COMMIT))msg.inReplyTo=COMMIT; elsemsg.inReplyTo=EMPTY_STRING; sendMessage((Agent)knownAgents.get(sendItTo),THIS_IS_YOURS,msg.content,msg.inReplyTo+tag(name,THIS_IS_YOURS),msg.replyWith,msg.language); if (recency.containsKey(tempName=sendItTo))recency.remove(tempName); recency.put(tempName,msg.replyWith); } else if(tempStatus.message.performative.equals(RESTORE)) { problems.remove(msg.replyWith); sendMessage{(Agent)knownAgents.get(sendItTo),RESTORE,msg.content,tag(name,RESTORE),msg.replyWith,msg.language);} elseif(tempStatus.message.performative.eguals(DISSATISFIED)){ problems.remove(msg.replyWith); sendMessage((Agent)knownAgents,get(sendItTo),DISSATISFIED,msg.content,tag(name,DISSATISFIED),msg.replyWith,msg.language);} } else if ((TheyKnowCount==0) || (TheyKnowcount+TheyMayKnowCount>1)){//Everyone has said this problem isn't their's,or there's a conflictif(tempStatus.message.per formative.equals(IS_THIS_YOURS)) { problems.remove(msg.repIyWith); problems.put(msg.replyWith,tempStatus); } if (tagged(msg.inReplyTo,EMPTY_STRING,COMMIT)){ if ((TheyMayKnowCount==1) &&(TheyKnowCount==0)) {problems.remove(msg.replyWith);if (tagged(msg.inReplyTo,EMPTY_STRING,COMMIT))msg.inReplyTo=COMMIT;sendMessage((Agent)knownAgents.get(AgentsWhoMayKnow.substring ( 1,AgentsWhoMayKnow.length()-1)),THIS_IS_YOURS,								msg.content,msg.inReplyTo+tag(name,THIS_IS_YOURS),meg.replyWith,msg.language);if (recency.containsKey(tempName=AgentsWhoMayKnow.substring(1,AgentsWhoMayKnow.length()-1))) recency.remove(tempName);recency.put(temp Name,msg.replyWith);} else (if (!sendThemAll(sender,tempStatus)) {temp Status.message.performative=msg.performative;tempStatus.message.inReplyTo=msg.inReplyTo;sendNessage((Agent)knownAgents.get(MenuAgent.instance.name),ASK_OPTIONS_FROM_USER,makeQuestionString(tempStatus,sender),msg.inReplyTo,msg.replyWith,msg.language); return; }} } else if(!tempStatus.message.performative.equsls(THIS_IS_YOURS)) if ((TheyMayKnowCount=0) &&(TheyKnowCount==0))sendMessage((Agent)knoMnAgents.get(tempStatus.message.sender),NOT_MINE,msg.content,msg.inReplyTo,msg.language);msg.replyWith, else if ((TheyKnowCount>1) &&(onFocuses))/★★/sendMessage((Agent)knownAgents.get(tempStatus.messsge.sender),IT_IS_MINE,msg.content,msg.inReplyTo,msg.replyWith,resultingFocus,tempStatus.maxPriority);elsesendMessege((Agent)knownAgents.get(tempStatus.message.sender),MAYBE_MINE,meg.content,msg.inReplyTo,meg.replyWith,msg.content,tempStetus.maxPriority);//★ else if((tempStatus.message.performative.equals (THIS_IS_YOURS)) &&( (TheyKnowCount>1)||(TheyMayKnowCount>1))){if (!sendThemAll(sender,tempstatus)){sendMessege((Agent)knownAgents.get(tempStatus.message.sender),MAYBE_MINE,meg.content,msg.inReplyTo,msg.replyWith,msg.content,tempStatus.maxPriority);//★ }} else { interpretIt(msg.content,msg.content.toLowerCase().trim(),msg);sendMeesege((Agent)knownAgents.get(tempStatus.message.sender),MAYBE_MINE,msg.content,msg.inReplyTo,								msg.replyWith,msg.content,tempStatus.maxPrlority);//★}}}public synchronized boolean greaterOrEqualRecency(String r1,String r2) {r1=(String)recency.ger(r1);r2=(String)recency.get(r2);if ((r1!=null) && (r2==null)) return true;if ((r1==null) && (r2==null)) return true;if ((r1==null) && (r2!=null)) return false;Integer templ=newInteger(r1.substring(r1.indexOf("#")+1,r1.length()));Integer temp2=newInteger(r2.substring(rl.indexOf("#")+1,r2.length()));if (templ.intValue()>=temp2.intValue()) return true; else return false;}public synchronized boolean greaterRecency(String r1,stringr2)(r1=(string)recency.get(rl);r2=(String)recency.get(r2);if ((r1!=null) && (r2=null))return true;if ((r1==null) && (r2==null))return false; if ((r1==null) && (r2!=null))return false;Integer temp1=newInteger(r1.substring(r1.indexOf("#")+1,r1.length()});Integer temp2=newInteger(r2.substring(r1.indexOf("#")+1,r2.length()));if (temnp1.intValue()>temp2.intValue()) return true;else return false;}public synchronized boolean equalRecency(String r1,String r2){ r1=(String)recency.get(rl); r2=(String)recency.get(r2) if ((r1!=null) && (r2==null))return false; if ((r1==null) && (r2==null))return true;if ((r1==null) && (r2!=null))return false;Integer temp1=newInteger(r1.substring(r1.indexOf("#")+1,r1.length()));Integer temp2=newInteger(r2.substring(rl.indexOf("#")+1,r2.length()));if (temp1.intValue()==temp2.intValue())return true;else return false;}								 public synchronized String focus(AgentStatus tempStatus,String theName,String delim){int index=tempStatus.notMineAgentList.index0f(tag(theName,delim))+theName.length()+delim.length()+1;String prior=tempstatus.notMineAgentList.substring(index,tempStatus.notMineAgentList.indexOf(NUMBER_DELIMITER,index));int index2=index+priot.length()+1;return tempstatus.notMineAgentList.substring(index2,tempStatus.notMineAgentList.indexOf(NUMBER_DELIMITER,index2));}public synchronized boolean checkFocuses(AgentStatustempStatus,String theName,String delim,String priot){String remainder;int index;if (delim.equals(IT_IS_MINE))remainder=AgentsWhoKnow;elseremainder=AgenteWhoMayKnow; if ((remainder.length()==0) &&(!theName.equals(tempStatus.maxPriorityAgentName))){ String tempFocus2=focus(tempStatus,theName,delim); if ((!theName.equals(tempStatus.maxPriorityAgentName)) &&((!betterFocus(tempFocus2,tempStatus.maxLanguage)) &&(!equalFocus(tempFocus2,tempStatus.maxLanguage)))) return false;return true;}while(remainder.length()!=0){string check=remainder.substring(1,index=remainder.indexof(IT_IS_MINE,2)));remainder=remainder.substring{index+1,remainder.length());String tempFocusl = focus(tempStatus, check, delim);String tempFocus2 = focus(temRStatus, theName, delim);if ((!theName.equals(check)) && (!betterFocus(tempFocusl,tempFocue2)) && (!equalFocus(tempFocusl,tempFocus2)))return false;}return true;}public synchronized boolean priorityMatches(AgentStatustempStatus,string theName,String delim){string reguestFocus=focus(tempstatus,theName,delim);int index=tempStatus.notMineAgentList.indexof(tag(theName,delim})+theName.length()+delim.length()+1;String prior=tempStetus.notMineAgentList.substring(index,tempStatus.notMineAgentList.indexof(NUMBER_DELIMITER,index));int index2=index+prior.length();if ((tempStatus.notMineAgentList.indexOf(tag(requestFocus,NUMBER_DELIMITER))==index2) && (checkFocuses(tempStatus,theName,delim,priot)))return true; else { if(prior.equals(Integer.tostring(tempStatus.maxPriority))){if ((recency.containsKey(theName)}||(recency.containsKey(tempstatus.maxPriorityAgentName)))if (greaterOrEqualRecency(theName,tempstatue.maxPriorityAgentName})								 return true; else return false;return true; } returnfalse;}}public synchronized void dissatisfactlon(AgentMessage msg){ processIt(msg.content); Enumeration cat=Communities.keys(); String question=EMPTY_STRING; for (int index=1;Cat.hasMoreElements();index++}{ String temp=(string)explanations.get((string)cat.nextElement()); if (question.indexOf(temp)<0)question=question+temp+OPTION_SEPARATOR; } tempStatus=new AgentStatus(new AgentMessage(msg),EMPTY_STRING,new AgenTMessage(lastMessage),0, EMPTY_STRING, EMPTY_STRING,EMPTY_STRING); if (!problems.containsKey(msg.replywith))probiems.put(msg.replyWith,tempstatus);sendMessage((Agent))knownAgents.get(MenuAgent.instance.name),ASK_OPTIONS_FROM_USER,question+IGNORE_OPTION+OPTION_SEPARATOR, msg.inReplyTo,msg.replywith,msg.language);}public synchronized void receiyedAdvertise(){//Agentwants to tell me it can handle questions concerning content.Agent sender=(Agent)knownAgents.get(msg.sender); if(!getCommunity(msg.content.toLowerCase().trim()).equals(EMPTY_STRING)){ Vector agents=(Vector)communities.get(msg.content.toLowerCase().trim()); agents.addElement(sender); } else { Vector agents=new Vector(); communities.put(msg.content.toLowerCase().trim(),agents);agents.addElement(sender); } learned.put(EXACT_MATCH+msg.content.toLowerCase().trim(),msg.content.toLowerCase().trim()); if (lmsg.ontology.equals(EMPTY_STRING))explanations.put(msg.content.toLowerCase().trim(),msg.ontology); elseexplanations.put(msg.content.toLowerCase().trim(),msg.content.toLowerCase().trim());}public synchronized void receivedUnAdvertise(){//Agentwants me to remove it from the community.Agent sender=(Agent) knownAgents.get(msg.sender);								if(!getCommunity(msg.content.toLowerCase().trim()).equals(EMPTY_STRING)){ Vector agents=(Vector)communities.get(msg.content.toLowerCase().trim()); agents.removeElement(sender); if (agents.size()==0)communities.remove(msg.content.toLowerCase().trim()); } if(explanations.containsKey(msg.content.toLowerCase().trim()))explanations.remove(msg.content.toLowerCase().trim());}public synchronized void receivedInterpretationRequest(){ // Agent says this item is mine and I should process androute it or is asking whether this item is mine or not.Agent sender=(Agent)knownAgents.get(msg.sender);Agent agent; if (problems.containsKey(msg.replyWith)) if (!tagged(msg.inReplyTo,EMPTY_STRING,C0MMIT)){ if (tempStatus.processed){ tempStatus.message=new AgentMessage(msg); if ((msg.performative.equals(THIS_IS_YOURS))||(msg.performative.equals(DISSATISFIED)))processedItem=processIt(msg.content);//Normally should not change item.else if(msg.performative.equals(RESTORE)) processedItem=unRrocessIt(msg.content); else processedItem=msg.content.toLowerCase().trim(); processAnswers(sender,tempStatus,msg);return;} else problems.remove(msg.replyWith};} else {tempStatus.message.inReplyTo+=COMMIT;if ((msg.performative.equals (THIS_IS_YOURS))||(msg.performative.equals(DISSATISFIED)))processedItem=processIt(msg.content);//Normallyshould not change item.else if (msg.performative.equels(RESTORE)) processedItem=unProcessIt(msg.content); else processedItem=msg.content.toLowerCase().trim();processAnswers(sender,tempStatus,msg);return; } AgentMessage tempMsg=new AgentMessage(msg); perform(msg,sender,OPTIMISE);}public synchronized void receivedNotMine(){//agentsaysthis item does not belong to it.Agent sender=(Agent) knownAgents.get(msg.sender) ;if (problsms.containsKey(msg.replyWith)){ if (!tagged(tempStatus.interpretations,IT_IS_MINE,sender.name))tempStatus.notMineAgentList=tempStatus.notMineAgentList+tag(sender.name, NOT_MINE); else (								int temp=tempstatus.interpretations.indexOf(tag(sender.name,IT_IS_MINE));String requestFocus=tempStatus.interprpretations.substring(temp+sender.name.length()+2*IT_IS_MINE.length(),tempStatus.interpretations.indexOf(NUMBER_DELIMITER,temp));insertOutcome(IT_IS_MINE,priority,requestFocus);}processAnswers(sender,tempstatus,msg); } else System.out.println("WARNING!["+name+"]:ANot-Mine!received from"+sender.name+"for an unknownproblem:"+msg.content+":"+msg.replyWith);}public synchronized boolean betterFocus(String newFocus,String oldFocus){return ((newFocus.length()<oldFocus.length()) && ((newFocus.equals(EMPTY_STRING))||(oldFocus.indexOf(newFocus)>NONE)) };}public synchronized boolean equalFocus(string newFocus,StringoldFocus){return ((!newFocus.equals(oldFouus)) &&((newFocus.indexOf(oldFocus)==N0NE) &&(oldFocus.indexOf(newFocus)==NONE))};}public synchronized void cleanList(String theName){int index=tempStatus.notMineAgentList.indexOf(tag(theName,IT_IS_MINE));If (index=NONE)index=tempStatus.notMineAgentList.indexOf(tag(theName,MAYBE_MINE));int ind2=1+tempStatus.notMineAgentList.lndexOf(NUMBER_DELIMITER,tempStatus.notMineAgentList.indexOf(NUMBE_DELIMITER,index)+NUMBER_DELIMITER.length());//d("WAS"+tempStatus.notMineAgentList);tempStatus.notMineAgentList=tempStatus.notMineAgentList.substring(0,index)+tempStatus.notMineAgantList.substring(ind2,tempStatus.notMineAgentList.length());tempStatus.notMineAgentList=tempStatus.notMineAgentList+NOT_MINE); tag(theName,//d("BECAME"+tempStatus.notMineAgentList);}public synchronized void insertOutcome(StringtempPerformative,int mp,String requestFocus){Agent sender=(Agent)knownAgents.get(msq.sender); if ((tempStatus.maxPriority<mp)||((tempStatus.maxPriority==mp) &&((grea terRecen cy(sender.name,tempStatus.maxPriorityAgentName))||								((tempStatue.maxPriority==mp) &&(equalRecency(sender.name,temp.status.maxPriorityAgentName)) &&(requestFocus.equals(tempStatus.maxLanguage)))||((betterFocus(requestFocus,tempStatus.maxLanguage))&&(tampStatus.notMineAgentList.indexOf(tag(requestFocus,NUMBER_ELIMITER))=NONE))))||((onlyone()==false) &&(betterFocus(requestFocus,tempStatus.maxLanguage)))){ if ((tempStatus.maxPriority>=mp) && (onlyOne()==false) &&(!((tempStatus.maxPriority==mp} &&((greaterRecency(sender.name,tempStatus.maxpriorityAgentName))||((tempStatus.maxPriority==mp) &&(equalRecency(sender.name,tempStatus.maxPriorityAgentName)) &&(requestFocus.equals(tempStatus.maxLanguage)))}}} &&(betterFocus(requestFocus,tempStatus.maxLanguage)))cleanList(tempStatus.maxPriorityAgentName); tempStatus.notMineAgentList=tempstatus.notMineAgentList+tag(sender.name,tempPerformative)+mp+NUMBER_DELIMITER+requestFocus+NUMBER_DELIMITER;tempStatus.maxPriority=mp;tempStatus.maxLanguage=requestFocus;tempStatus.maxPriorityAgentName=sender.name;} else tempStatus.notMineAgentList=tempStatus.notMineAgentList+ tag(sender.name,NOT_MINE);}public synchronized String merge(String source,String s1,String s2){String tempResult=EMPTY_STRING;//d("WAS:"+s1+":"+s2);if (!source.equals(EMPTY_STRING)){iht i=0;while ((i<s1.length()) && (i<s2.length()) &&(s1.charAt(i)==source.charAt(i)) &&(s2.charAt(i)==source.charAt(i)))1++;tempResult+=source.substring(0,i);i=source.langth()-1;int i1=s1.length()-1;int i2=s2.length()-1;while ((i1>0) && (i2>0) &&(si.charAt(i1)==source.charAt(1)) &&(s2.charAt(i2)==source.charAt(i))){ i--; i1--; i2--; } tempResult+=source.substring(i+1,source.length());//d("BECAME:"+tempResult);return tempResult; }								public synchronized void receivedMine()( //agent saysthis item may belong to it or agent says this item does belongto it.Agent sender=(Agent)knownAgents.get(msg.sender);int temp;String requestFocus;if (problems.containsKey(msg.replyWith)){if ((!tagged(tempStatus.notMineAgentList,IT_IS_MINE,msg.sender)) && (!tagged(tempStatus.notMineAgentList,MAYBE_MINE,msg.sender))){ int mp=Integer.valueof(msg.ontology).intValue(); String tempPerformative; if (!tagged(tempStatus.interpretations,IT_IS_MINE,sender.name))( requestFocus=msg.language; if (msg.performative.equals(MAYBE_MINE))tempPerformative=MAYBE_MINE; else tempPerformative=IT_IS_MINE;}else {tempPerformative=IT_IS_MINE;mp=priority;temp=tempStatus.interp retations.indexOf(tag(sender.name,IT_IS_MINE));requestFocus=tempStatus.interpretations.substring(temp+sender.name.length()+ 2★IT_IS_MINE.length(),tempStatus.interprstations.indexOf(NUMBER_DELIMITER,temp));if (!requestFocus.equals(msg.language))if ((temp=requestFocus.indexOf(msg.language))>NONE) requestFocus=requestFocus.substring(0,temp)+requestFocus.substring(temp+msg.language.length(),requestFocus.length());else if ((temp=msg.language.indexOf(requestFocus))>NONE) requestFocus=msg.language.substring(0,temp)+meg.language.substring(temp+requestFocus.length(),msg.language.length());else If (!requestFocus.equals(msg.language)) requestFocus=merge(msg.content,requestFocus,msg.language); } insertoutcome(tempPerformative,mp,reguestFocus); processAnswers(sender,tempStatus,msg); }elsesendMessage((Agent)knownAgents.get(tempStatus.message.sender),MAYBE_MINE,msg.content,msg.inReplyTo, msg.replyWith,msg.language,tempStatus.maxPriority);} else System.out.println("WARNING ("+name+"):AMaybe-Mine!or It-is-Mine!received from"+sender.name+"foran unknown problem:"+msg.content+":"+msg.replywith);}public synchronized void receivedLearn(){//agent says Ishould learn (or unify the effect of these two requests)int index;								 Agent sender=(Agent)knownAgents.get(meg.sender); if (!problems.containsKey(msg.replyWith)) tempStatus=new AgentStatus(new AgentMessage(msg),EMPTY_STRING, new AgentMessage(lastMessage),0,EMPTY_STRING,EMPTY_STRING,EMPTY_STRING);String item=msg.content;String processedItem=item.toLowerCase().trim();Interpretation interpretation=interpretIt(item,processedItem,msg);String whichAgent=toWhom(item,processedItem,interpretation.result);learn(tempStatus,interpretation.result,whichAgent);Enumeration agents=knownAgents.elements();Agent tempAgent;for(index=1;agents.hasMoreElements();index++){tempAgent=(Agent)agents.nextElement();sendMessage(tempAgent,UN_LEARN,processedItemEMPTY_STRING,msg.replywith,msg.language); }problems.remove(msg.replyWith);//remove registeredproblem.}public synchronized void receivedUnLearn(){//agent saysI should forget what I've learned about a certain request.int index;Agent sender=(Agent)knownAgents.get(msg.sender); if (learned.contsinsKey(EXACT_MATCH+msg.content.toLowerCase().trim())){String item=msg.content.toLowerCase().trim();Interpretation interpretation;while ((interpretation=interpretIt(item,item,msg))!=null) {Vector agents=Vector)communities.get(interpretation.result);int hum=agents.size();for (index=0;index<num;index++}if (sender==(Agent)agents.elementAt(index)) {unlearn (item);return;} item=interpretation.remainderRequeet;} }}public synchronized void receivedDissatisfied(){//agentsays a conflict has occured on a certain request. String item=msg.content; String processedItem=item.toLowerCase().trim(); //If I don't have any communities under me I shoulddisregard command if ((communities.size()==0) && (interpretIt(item,processedItem,msg)=null)) return; dissatisfaction(msg); return;}								public synchronized void receivedForgetProblem(){//agentsays I should disregard a certain problem. problems.remove(msg.replyWith);//remove registeredproblem.}public synchronized void receivedUserResponse(){Agent sender=(Agent)knownAgents.get(msg.sender);Agent agent;if (problems.containsKey(msg.replyWith)){ tempStatus=newAgentStatus((AgentStatus)problems.get(msg.replyWith)); if (!msg.content.equals(IGNORE_OPTION)}{ String userResponse=unexplain(msg.content); Interpretation interpretation; if (!knownAgents.containsKey(userResponse))if ((interpretation=interpretIt(userResponse,userResponse.toLowerCase().trim(), msg))!=null)userResponse=interpretation.result;elseSystem.out.println("WARNING!["+name+"]:Wrong user input:"+msg.content); learn(tempStatus,userResponse,EMPTY_STRING); for (Enumeration agents=knownAgents.elements();agents.hasMoreElements();){ agent=(Agent)agents.nextElement(); sendMessage(agent,UN_LEARN,tempStatus.message.content, EMPTY_STRING,tempStatus.message.replyWith,EMPTY_STRING); } perform(tempStatus.message,sender,!OPTIMISE); } }}public synchronized void route{AgentMessage msg) {if (problems.containsKey(msg.replyWith))tempStatus=newAgentStatus((AgentStatus)problems.get(msg.replyWith));processOtherMessages(msg);if (msg.performative.equals(ADVERTISE)){ receivedAdvertise(); return;}else if (msg.perfermative.equals(UN_ADVERTISE)) {receivedUnAdvertise();return;} elseif (((msg.performative.equals(THIS_IS_YOURS))||(msg.performative.equals(RESTO_RE))||(msg.performative.equals(COMMIT))||(msg.performative.equals(IS_THIS_YOURS))) &&(!tagged(msg.inReplyTo, THIS_IS_YOURS,name)) && //Deadlock prevention(!tagged(msg.inReplyTo,RESTORE,name)) &&(!tagged(msg.inReplyTo,IS_THIS_YOURS,name))){ receivedInterpretstionRequest(); return; } else if (msg.performative.equals(NOT_MINE)){receivedNotMine();								 return;} elseif ((msg.perfornative.eguals(MAYBE_MINE)}|| (msg.performative.equals(IT_IS_MINE))) { receivedMine(); return;} elseif (msg.performative.equals (LEARN)){receivedLearn();return;} elseif (msg.performative.equals(UN_LEARN)){receivedUnLearn();return;} elseif((msg.performative.equsls(DISSATISFIED)) && (!tagged(msg.inReplyTo,DISSATISFIED,name)) && (!problems.containsKey(msg.replyWith))){ msg.inReplyTo+=tag(name,DISSATISFIED); receivedDissatisfied(); return; } else if (msg.performative.equals(FORGET_PROBLEM)){if ((problems.containsKey(msg.replyWith)) && (tempStatus.message.content.equals(msg.content)))receivedForgetProblem(); return; } else if (msg.performative.equals(USER_RESPONSE)){receivedUserResponse();return; } }}//★★★★★★★★★★★★★★★★★★★★★★★★★//Title: AAOSA3package AAOSA3;public interface AAOSAConstants{//Standard AAOSA Performativesstatic final String REGISTER="}";static final String ADVERTISE="$";static final String UN_ADVERTISE="@";static final String THIS-IS-YOUNS"=";static final String IS_THIS_YOURS="?";static final String COMMIT="!";static final String DISSATISFIED="%";static final String RESTORE="<";static final String IT_IS_MINE="+";static final String MAYBE_MINE="#";static final String NOT_MINE="-";static final String LEARN="&";static final String UN_LEARN="~";static final String FORGET_PROBLEM=":";static final String USER_RESPONSE=">";static final String ASK_OPTIONS_FROM_USER="^";static final String ASK_NUMBER_FROM_USER="$";								//Agent specific performatives:static final String EXECUTE="`ex`";static final String MORE= "'mo'";static final String LESS= "'le'";static final String JUMP= "'ju'";static final String ON=" 'on'";static final String OFF= "'of'";static final String RESTORE_JUMP="'re'";static final String STOP="'[]'";static final String FORWARD="'>>'";static final String REWIND="'<<'";static final String PAUSE="'| |'";static final String UNPAUSE="'(('";staticfinal String PLAY="'=>'";static final String RECORD="'<>'";static final String START_TIME_DATE="'st'";static final String TIME_DATE="'td'";static final string CLEAR_TEXT="'ct'";static final String REMOVE_WINDOW="'rw'";static final String ADD_WINDOW="'aw'";//internal per formativesstatic final String EXACT_MATCH="="://Menu Constantsstatic final String IGNORE_OPTION="Ignore it";//Handy Constantsstatic final int SLEEP_DURATION=100;//In milisecondsstatic final int MAX_NUMBER_IN_REQUEST=9999;static final String EMPTY_STRING="";static final string NUMBER_DELIMITER=";";static final String OPTION_SEPARATOR="||";static final int NONE=-1;static final boolean OPTIMISE=true;}

                              附录2

 Sample Text Input Agent(文本输入代理样本) Copyright1998 by Babak Hodjatand Dejima Corporationpackage AAOSA3;import java.awt.avent.event.*;import java.awt.*;public class TextInputAgent extends AAOSAAent{static final String MY_NAME="TextInput*;static TextInputAgent instance=null;//singletonpublic TextField textFieldl;//passed on by caller!boolean CommitIt=false;boolean NotSatisfied=false;long PollCount=1;long PauseCunt=10;//1 secondlong RequestID=1;String prevCommand=EMPTY_STRING;String lastCommand=EMPTY_STRING;//in Singleton design pattern,used to get single instancestatic public TextInputAgeut Instance(){ if (instance==null){ instance=new TextInputAgent(MY_NAME); } return instance;}public static aynchronized void register(AgentEvent e){ if (instance==null)instance=new TextInputAgent(); if(linstance.knownAgents.containsKey(((Agent)e.getSource()).geName())){instance.knownAgents.put(((Agent}e.getSource()).getName(),e.getSource());((Agent)e.getSource()).addAgentEventListaner(instance); instance.addAgentEventListener((Agent)e.getSource()); } else System.out.println("Agent"+instance.name+"did not register"+(Agent)e.getSource()).getName());}public TsxtInputAgent() {name=MY_NAME;}public TextInputAgent(String Name)(super(Name);}public synchronised void initializations(){								 msg=new AgsntMessage(REGISTER,name,null,null,null,null); AgentEvent e=new AgentEvent(this,msg) ; InputAgent.instance.register(e);//register agentwith InputAgent TVActuator.instance.register(e); textFieldl.setText(EMPTY_STRING); ProgramAddAgent.instance.register(e); MenuAgent.instance.register(e); super.initializations();}public ssynchronized void processOtherMessages(AgentMessagemsg) { if (msg.performative.equals(CLEAR_TEXT)){ textFieldl.setText (EMPTY_STRING); prevCommand=EMPYT_STRING; CommitIt=false; NotSatisfied=false; RequestID++;}}public synchronized void receivedMine(){//agent saysthis item may belong to it or agent says this item does belongto it. CommitIt=false; NotSatisfied=false; RequestID++;}void textFieldl_keyReleased(KeyEvent e){ PollCount=1; if ((|textFieldl.getText().equals(EMPTY_STRING)} &&(((e.getKeyCode()==e.VK_ENTER)||//daer wants job done "now!"(textFieldl.getText().toLowerCase().trim().indexOf("doit")>NONE).||(textFieldl. getText().toLowerCase().trim().indexOf("come on")>NONE)||(textFieldl.getText().toLowerCase().trim().indexOf("hurry up")>NONE)))) //User expressing dissatisfactionCommitIt=true;else if(e.getCode()==e.VK_ESCAPE)//userexpressing dissatisfaction NotSatisfied=true; } public synchronized void polling(){if ((|textFieldl.getText().equals(prevCommand)) &&(!taxtFieldl.getText().trim().equals(EMPTY_STRING)) &&{(PollCount++%PauseCoutt)==0)){//sendit								 if(textFieldl.getText().toLowexCase().trim().indexOf("undo")>NONE)sendMessage{(Agent)knownAgants.get(InputAgent.instance.name),RESTORE,lastCommand,tag(name,RESTORE),"#"+(RequestID-1),EMPTY_STRING); else if((textFieldl.getText(),toLowerCase().trim().indexOf("again")>NONE)||(textFieldl. getText().toLowerCase().trim().indexOf("one moretime")>NONE)|| (textFieldl.getTeXT().toLowerCase().trim().indexOf("once more")>NONE)) sendMesaage ((Agenr)knownAgents.get(InputAgent.instance.name),THIS_IS_YOURS,lastCommand,tag(name,THIS_IS_YOURS),"#"+(RequestID-1},EMPTY_STRING); else if(TextFieldl.getText().toLowerCase().trim().indexOf(" Sync")>NONE){ Test.TVVCR.sync(); Test.TVVCR.execute("V",Test.volumeLevel.intValue()); if (Test.soundStatus==false)Test.TVVCR.execute("V0",-1); Test.TVVCR.execute("CL",Test.colorLevel.intValue()); Test.TVVCR.execute("CT",Test.volumeLevel.intValue()); Test.TVVCR.execute("B"Test.brightnessLevel.intValue()); Test.TVVCR.execute("C"Test.channelNumber.intValue()); taxtFieldl.setText(EMPTY_STRING); prevCommand=EMPTY_STRING; CommitIt=false; NotSatisfied=false; RequestID++; } else { prevCcommand=textFieldl.getText(); lastCcommand=preCommand; sendMessage((Agent)knownAgents.get(InputAgent.instance.name),THIS_IS_YOURS,prevCommand,tag(name,THIS_IS_YOURS),"#"+RequestID,EMPTY_STRING); }} elseif {CommitIt) { if (!textFieldl.getText().equalse(prevCommand))//ifnot sent before sendMessage((Agent)knowkAgents.get(InputAgent.instance.name),THIS_IS_YOURS,								textFieldl.getText(),tag(name,THIS_IS_YOURS,),"#"+RequestID,EMPTY_STRING);CommitIt=false;prevCommand=textFieldl.getText();lastCommand=prevCommand;sendMessage{(Agent)knownAgents.get(InputAGent.instance.name),COMMIT,prevCommand,tag(name,COMMIT),"#"+(RequestID-1),EMPTY_STRING);} elseif (Notsatisfied){ NotSatisfied=false; textFieldl.setText(lastcommand); textFieldl.selectAll(); prevCommand=lastCommand; textFieldl.validate(); sendMessage((Agent)knowAgents.get(InputAgent.instance.name),RESTORE,lastCommand,tag(name,RESTORE),"#"+(RequestID-1),EMPTY_STRING); sendMessage((Agent))knownAgants.get(InputAgent.instance.name),DISSATISFIED,lastCommand,tag(rame,DISSATISFIED),"#"+RequestID,EMPTY_STRING);} }}

                               附录3

 Sample Input Regulator Agent(输入调节器代理样本) Copyright1998 by Babak Hodjaland Dejima Corporationpackage AAOSA3;public class InputAgent extends AAOSAAgent{static final String MY_NAME="Inputl";static final int MY_PRIORITY=100;static final String MY_COMMUNITY="Input";static InputAgent instance=null;//singletonstatic public InputAgent Instance(){ if (instance==null){instance=new InputAgent(MY_NAME); } return instance;}public static synchronized void register(AgentEvent e){ if (instance==null)instance=new InputAgent(); if(linstance.knownAgents.containsKey(((Agent)e.getSource()).getName())){instance.knownAgents.put(((Agent)e.getSource()).getName(),e.getSource());((Agent)e.getSource()).addAgentEventListener(instance); instance.addAgentEventListener((Agent)e.getSource()); } else System.out.println("Agent"+instance.name+"did not register"+((Agent)e.getSource()).getName()) ;}public InputAgent(){name=MY_NAME;prioriTY=MY_PRIORITY;}public InputAgent(String Name){super(Name,MY_PRIORITY);}public synchronized boolean onlyOne(){return true;}public synchronized void initialization(){ AgentMessage msg=new AgentMessage(REGISTER,name,null,null,null,null); AgentEvente=new AgentEvent(this,msg); ActionAgent.instance.register(e); TextInputAgent.instance.register(e); MenuAgent.instance.register(e); ProgramAgent.instance.register(e);// learned.put(EXACT_MATCH+"do",ActionAgent.instance.MY_COMMDNITY.toLowerCase().trim()};//default interpretations								 learned.put("programming",ProgramAgent.instance.MY_COMMUNITY.toLowerCase().trim()); learned.put("schedule",ProgramAgent.instance.MY_COMMUNITY.toLowerCase().trim()); learned.put("remember",ProgramAgent.instance.MY_COMMUNITY.toLowerCase().trim()); super.initializations();}}

                                 附录4

 Samnle TV Actuator Agent(TV致动器代理样本)Copyright1998 by Babak Hodjat and Dejima Corpocationpackage AAOSA3;import java.awt.*;import jclass.bwt.*;import borland.jbcl.layout.*;public class TVActuator extends AAOSAAgent{static TVActuatox instance=null;static final string MY_NAME="TVActuato=";Panel TV=new Panel();JCSlider Volume=new JCSlider();JCSlider Lights=new JCSlider();JCSlider Brightness=new JCSlider();JCSlider Contrast=new JCSlider();JCSlider Color=new JCSlier();JCCheckbox Soundoff=new JCCheckbox();JCCheckbox LightsOn=new JCCheckbox();JCCheckbox PowerOn=new JCCheckbox();XYLayout xYLayoutl=new XYLayout();Label tvchannelLabel=new Label();Label vcrFunctionLabel=new Label();Label vcrPauseLabel=new Label();Label vcrChannelLabel=new Label();Label dvdFunctionLabel=new Label();Label dvdPauseLabel=new Label();Label windowChannelLabel=new Label();jclass.bwt.JCSeparator jCSeparator1=newjclass.bwt.JCSeparator();jclass.bwt.JCSeparator jCSeparator2=newjclaas.bwt.JCSeparator();jclass.bwt.JCSeparator jCSeparator3=newjclass.bwt.JCSeparator();jclass.bwt.JCSeparator jCSeparator4=newjclaas.bwt.JCSeparator();jclass.bwt.JCSeparator jCSeparator5=newjclass.bwt.JCSeparator(); //in Singleton design pattern,used to get single instance static public TVActuator Instance(){if (instance==null){ instance=new TVActuator(MY_NAME);}return instance; } public static synchronized void register(AgentEvent e){if (instance==null) instance=new TVActuator();if(!instance.knownAgents.containsKey(((Agent)e.getSource()).getName())){								instance.knownAgents.put(((Agent)e.getSource()).getName(),e.getSource());((Agent)e.getSource()).addAgentEventListener(instance); instance.addAgentEventListener((Agent)e.getSource()); } else System.out.println("Agent"+instance.name+"did not register"+((Agent)e.getSource()).getName());}public TVActuator(){name=MY_NAME;try {jbInit();}catch(Exception e){e.printStackTrace(); }} public TVActuator(String Name){super(Name);try {jbInit ();}catch(Exception e){e.printStackTrace();}}public synchronized void initializations(){ AgantMessage msg=new AgentMessage(REGISTER,name,null,null,null,null); AgentEvent e=new AgentEvent(this,msg); VideoAgent.instance.register(e); DVDAgent.instance.register(e); WindowAgent.instance.register(e); PowerAgent.instance.register(e); SoundAgent.instance.register(e); LightaAgent.instance.register(e); BrightnessAgent.instance.register(e); ContrastAgent.instance.register(e); ColorAgent.instance.register(e); ChannelAgent.instance.register(e); TextInputAgent.instance.register(e); super.initializations();}public synchronised void startupDefaults(){displayEverything();}public synchronised void displayEverything(){ if (Test.soundStatus==true) Soundoff.setState(0); else Soundoff.setState(1); if (Test.powerStatus==true) PowerOn.setState(1); else PowerOn.setState(0);								Volume.setValue(Test.volumeLevel.intValue());if (Test.lightsStatus==true)LightsOn.setState(1);elseLightsOn.setState(0);Lights.setValue(Test.lightsLevel.intValue());Color.setValue(Test.colorLevel.intValue());Contrast.setValue(Test.ContrastLevel.intValue());Srightness.setValue(Test.brightnessLevel.intValue());tvchannelLabel.setText("Channel"+Test.channelNumber.toString());vcrFunctionLabel.setText("VCR:STOP");if (Test.recordStatus==true)vcrFunctionLabel.setText("VCR:RECORD");if (Test.playStatus==true)vcrFunctionLabel.setText("VCR:PLAY");if (Test.rewindStatus==true)vcrFunctionLabel.setText("VCR:REWIND");if (Test.forwardStatus==true)vcrFunctionLabel.setText("VCCR:FORWARD");if (Test.pauseStatus==true)vcrPauseLabel.setText("PAUSE"); elsevcrPauseLabel.setText (" " ); vcrChannelLabel.setText("Channel"+Test.videoChannelNumber.toString()); if (Test.windowStatue==true) windowChannelLabel.setText("PIP:ON"/* +Test.windowChannelNumber.toString() */);elsewindowChannelLabel.setText("PIP:OFF");dvdFunctionLahel.setText("DVD:STOP");if (Tsst.dvdplayStatus==true)dvdFunctionLabel.setText("DVD:PLAY");if (Test.dvdrewindStatus==true)dvdFunctionLabel.setText("DVD:REWIND");if (Test.dvdforwardStatus == true)dvdFunctionLabel.setText("DVD: FORWARD");if (Test.dvdpauseStatus==true)dvdPauseLabel.setText("PAUSE");elsedvdPauseLabel.setText(" ");}public synchronized void processOtherMessages(AgentMessagemsg){ if (msg.performative.equals(EXECUTE)){if (msg.content.indexOf(PowerAgent.instance.name)==0){//POWERif (msg.content.indexOf(ON)==PowerAgent.instance.name.length()){//ONSystem.out.println("===>Executing:POWER ON\n");Test.TVVCR.execute("PW",-1);} else								if (msg.content.indexOf(OFF)==PowerAgent.instance.name.length()){//OFFSystem.out.println("===>Executing:POWEROFF\n");Test.TVVCR.execute("PWO",-1);} elss d("WARNING!Wrong message content:"+msg.content);} elseif (msg.content.incdexOf(SouncdAgent.instance.name)==0){//SOUND if (msg.content.indexOf(ON)==soundAgmnt.instance.name.length()){//ONSystem.out.println("===>Executing:SOUND ON\n");Test.TVVCR.execute("VO",-1);} else if (msg.content.indexOf(OFT)==SoundAgent.instance.name.length()){//OFFSystem.out.println("===>Executing:SOUNDOFF\n");Test.TVVCR.execute("VO",-1);} eleeif (msg.content.indexOf(MORE)==SoundAgent.instance.name.length()){//MORESystem.out.println("===>Executing:SOUMDMORE\n");Test.TVVCR.execute("V",1);} elseif (msg.content.indexOf(LESS)==SoundAgent.instance.name.length()){//LESSSystem.out.println(" ===>Executing:SOUNDLESS\n"); Test.TVVCR.execute("V",-1) ;} elseif (msg.content.indexOf(JUMP)==SoundAgent.instance.name.length()){//JUMPInteger jumpValue=newInteger(msg.content.substring(msg.content.indexOf(JUMP)+JUMP.length(),msg.contant.length())); System.out.println("===>Executing:sSOUND JUMP TO"+jumpValue.toString()+"\n"); Test.TVVCR.execute("V",Test.volumeLevel.intValue()-Test.previousVolumeLevel.intValue()) ; } else d("WARNING!Wrong message content:"+msg.contant);} elseif (meg.content.indexof(LightsAgent.instance.name)==0){//LIGHTSif (msg.content.indexOf(ON)==LightsAgent.instauce.name.length()){//ON System.out.println("===>Executing:LIGHTSOm\n"); } else								 if (msg.content.indexOf(OFF)==LightsAgent.inetance.name.1ength()){//OFFSystem.out.println("===>Executing:LIGHTSOFF\n");} elseif (msg.content.indexOf(MORE)==LightsAgent.instance.name.length()){//MORESystem.out.println("===>Executing:LIGHTSMORE\n");} elseif (msg.content.indexOf(LESS)==LightsAgent.instance.name.length()){//LESSSystem.out.println("===>Executing:LIGHTSLESS\n"}; } else if (msg.content.indexOf(JUMP)==LightsAgent.instance.name length()){//JUMPInteger jumpValue=newInteger(msg.content.substring(msg.content.indexOf(JUMP)+JUMP.length(),msg.content.length())); System.out.println("===>Executing:LIGHTS JUMPTO" + jumpValue.toString()+"\n");} else d("WARNING!Wrong message content:"+msg.content);} elseif (msg.content.indexOf(ColorAgent.instance.name)==0){//COLOR if (msg.content.indexOf(MORE)==ColorAgent.instance.name.length()){//MORESystem.out.println("===>Executing:COLORMORE\n");Test.TVVCR.execute("CL",1);} elseif (msg.content.indexOf(LESS)==ColorAgent.instance.name.length()){//LESSSystem.out.println("===>Executing:COLORLESS\n");Test.TVVCR.execute("CL",-1);} elseif (msg.content.indexOf(JUMP)==ColorAgent.instance.name.length()){//JUMPInteger jumpValue=newInteger(msg.content.substring(msg.content.inOf(JUMP)+JUMP.length(),msg.content.length())); System.out.println("===>Executing:COLOR JUMP TO"+jumpValue.toString()+\"n") ; Test.TVVCR.execute("CL",Test.colorLevel.intValue()-Test.previousColorLevel.intValue()); } else d("WARNING!Wrong message content:"+msg.content);} elseif (msg.content.indexOf(ContrastAgent.instace.name)==0){//CONTRAST								if (msg.content.indexOf(MORE)==ContrastAgent.instance.name.length()){//MORESystem. out.println("===>Executing:CONTRASTMORE\n") ;Test.TVVCR.execute("CT",-1); } elseif (msg.contant.indexOf(LESS)==ContrastAgent.instance.name.length()){//LESSSystem.out.println("===>Executing:CONTRASTLESS\n");Test.TVVCR.execute("CT",-1);} elseif (msg.contant.indexOf(JUMP)==ContrastAgent.instance.name.length()){//JUMPInteger jumpValue=newInteger(msg.content.substring(msg.content.indexOf(JUMP)+JUMP.length(),msg.content.length()));System.out.println("===>Executing:CONTRAST JUMPTO"+ jumpValue.toString()+"\n");Test.TVVCR.execute("CT",Test.volumeLevel.intValue()-Test.previousVolumeLevel.intValue());} else d("WARNING!Wrong message content:"+msg.Cohtent);} elseif(msg.content.indexOf(BrightnessAgent.instance.name)==0){//BRIGHTNESSif (msg.contant.indexOf(MORE)==BrIghtnessAgent.instance.name.length()){//MORESystem.out.println("===>Executing:BRIGHTNESSMORE\n");Test.TVVCR.execute("B",1);} elseif (msg.contant.indexOf(LESS)==BrIghtnessAgent.instance.name.length()){//LESSSystem.out.println("===>Executing:BRIGHTNESSLESS\n");Test.TVVCR.execute("B",-1); }else if (msg.contant.indexOf(JUMP)==BrIghtnessAgent.instance.name.length()){//JUMPInteger jumpValue=newInteger(msg.content.substring(msg.content.indexOf(JUMP)+JUMP.length(), msg.content.length()));System.out.println("===>Executing:BRIGHTNESSJUMP TO"+jumpValue.toString()+"\n");Test.TVVCR.execute("B",Test.brightnessLevel.intValue()-Test.previousBrightnessLevel.intValue()) ;} else d("WARNING!Wrong message content:"+msg.content);} else								 if(msg.content.indexOf(TelevisionAgent.instance.name)==0)(//TELEVISIONif (msg.content.indexOf(MORE)==TelevisionAgent.instance.name.length()){//MORESystem.out.println("===>Executing:TELEVISIONCHANNEL NEXT\n");Test.TVVCR.execute("C",Test.channelNumber.intValue());} elseif (msg.content.indexOf(LESS)==TelevisionAgent.instance.name.length()){//LESSSystem.out.println("===>Executing:TELEVISIONCHANNEL PREVIOUS\n");Test.TVVCR.execute("C",Test.channelNumber.intValue());} elseif (msg.content.indexOf(JUMP)==TelevisionAgent.instance.name.length()){//JUMPInteger jumpValue=newInteger(meg.content.substring(meg.content.indexOf(JUMP)+JUMP.length(),msg.content.length())); System.out.println("===>Executing:TELEVISIONCHANNEL JUMP TO"+jumpValue.toString()+"\n"); Test.TVVCR.execute("C",Test.channelNumber.intValue());} else d("WARNING!Wrong message content:"+msg.content);} elseif (msg.content.indexOf(VideoAgent.instance.name)==0){//VIDEO if (msg.content.indexOf(RECORD)==VidsoAgent.instance.name.length()){//RECORDSystem.out.println("===>Executing:VIDEORECORD\n");Test.TVVCR.executs("R",-1);} elseif (msg.content.indexOf(PLAY)==VideoAgant.instance.name.length()){//PLAYSystem.out.println("===>Execulting:VIDEOPLAY\n");Test.TVVCR.execute("PL",-1);} elseif (msg.content.indexOf(PAUSE)==VideoAgent.instance.name.langth()){//PAUSESystem.out.println("===>Executing:VIDEOPAUSE\n");Test.TVVCR.execute("P",-1);} elseif (msg.content.indexOf(UNPAUSE)==VideoAgent.instance.name.length()){//UNPAUSESystem.out.println("===>Executing:VIDEOUNPAUSE\n");vcrPauseLabel.setText("");Test.TVVCR.execute("S",-1);								} elseif (msg.content.indexOf(STOP)==VideoAgent.instance.name.length()) {//STOPSystem.out.println("===>Executing:VIDEOSTP\n");vcrFunctionLabel.setText("VCR:STOP");Test.TVVCR.execute("S",-1);Test.TVVCR.execute("C",Test.channelNumber.intValue());} elseif (msg.content.indexOf(REWIND)==VideoAgent.instance.name.length()){//REWINDSystem.out.println("===>Executing:VIDEOREWIND\n");Test.TVVCR.execute("RW",-1);} elseif (msg.content.indexOf(FORWARD)==VideoAgent.instance.name.length()){//FORWARDSystem.out.println("===>Executing:VIDEOFORWARD\n");Test.TVVCR.execute("F",- 1);} else if (msg.content.indexOf(MORE)==VideoAgent.instance.name.length()){//MORKSystem.out.println("===>Executing VIDEO CHANNELNEXT\n");Test.TVVCR.execute("CV",Test.channelNumber.intValue());} elseif (msg.content.indexOf(LESS)==VideoAgent.instance.name.length()){//LESSSystem.out.println("===>Executing VIDEO CHANNELPREVIOUS\n");Test.TVVCR.execute("CV",Test.channelNumber.intValue()); } else if (msg.content.indexOf(JUMP)==VideoAgent.instance.name.length()){//JUMPInteger jumpValue=newInteger(msg.content.substring(msg.content.indexOf(JUMP)+JUMP.length(),msg.content.length())));System.out.println("===>Executing VIDEO CHANNELJUMP TO"+jumpValue.toString()+"\n");Test.TVVCR.execute("CV",Test.videochannelNumber.intValue());} else d("WARNING!Wrong message content:"+msg.content);} elseif (msg.content.indexOf(WindowAgent.instance.name)==0){//WINDOWif (msg.content.indexOf(ADD_WINDOW)==WindowAgent.instance.name.length()){//ADDSystem.out.println("===>Executing:WINDOWADD\n");Test.TVVCR.pipDisplay(true);								elseif (msg.content.indexOf(REMOVE_WINDOW)==WindowAgent.instance.name.length())(//REMOVESystem.out.pzintln("===>Executing:WINDOWREMOVE\n");Test.TVVCR.pipDisplay(false); } else if (msg.content.indexOf(MORE)==WindowAgent.instance.name.length()){//MORESystem.out.println("===>Executing:WINDOWCHANNEL NEXT\n"};Test.TVVCR.pipChannelNext();} elseif (msg.content.indexOf(LESS)==WindowAgent.instance.name.length()){//LESSSystem.out.println("===>Fxecuting:WINDOWCHANNEL PREVIOUS\n");Test.TVCCR.pipChannelPrev();} elseif (msg.content.indexOf(JUMP)==WindowAgent.instance.name.length()){ //JUMPInteger jumpValue=newInteger(mag.conteht.substring(msg.content.indexOf(JUMP)+JUMP.length(),msg.conteut.length())) ; System.out.println("===>Executing:WINDOWCHANNEL JUMP TO"+jumpValue.toString()+"\n");Test.TVVCR.pipSetChannel(Test.windowChannelNumber.intValue()-Test.previousWindowChannelNumber.intValue());} else d("WARNING!Wrong message content:"+mag.ccntent);} elseif (mag.content.indexOf(DVDAgent.insuance.name)==0){//DVDif (msg.content.indexOf(PLAY)==DVDAgenT.instance.name.length()){//PLAYSystem.out.println(" ===>Executing:DVD PLAY\n");Teet.TVVCR.selectDvd();Test.TVVCR.dvdPlay();} elseif (msg.content.indexOf(PAUSE)==DVDAgent.instance.name.length()){//PAUSESystem.out.println("===>Executing:DVDPAUSE\n");Test.TVVCR.dvdPause(); } elseif (msg.content.indexOf(UNPAUSE)==DVDAgent.instance.name.length()){//UNPAUSESystem.out.println("===>Executing:DVDUNPAUSE\n");dvdPauseLabel.setText(" " );Test.TVVCR.dvdPlay();} else if (msg.content.indexOf(STOP)==DVDAgent.instance.name.length()){//STOP								System.out.println("===>Executing:DVD STOP\n");Test.TVVCR.dvdStop();Test.TVVCR.dvdStop();Test.TVVCR.execute("C",Test.channelNumber.intValue());} elseif (msg.content.indexOf(REWIND)==DVDAgeut.instance.name.length()){//REWINDSyetem.out.println("===>Executing:DVDREWIND\n");Test.TVVCR.dvdScanReverse();} elseif (msg.content.indexOf(FORWARD)==DVDAgent.instance.name.length()){//FORWARDSystem.out.println("===>Executing:DVDFORWARD\n") ;Test.TVVCR.dvdScanForward();} elsed("WARNING!Wrong message content:"+meg.content);}displayEverything();sendMessage((Agent)knownAgents.get(TextInputAgent.instance.name),CLEAR_TEXT,EMPTY_STRING,,KMPTY_STRTNG,msg.replyWith,EMPTY_STRING); }}public synchronized void jbinit()throws Exception{TV.setEnabled(false);TV.setForeground(SystemColor.inactiveCaption);TV.setLocale(new java.util.Locale("en","GB",EMPTY_STRING));TV.satLocation(new Point(50,50));TV.setSize(new Dimnsion(537,300));TV.setLayout(xYLayoutl);Volume.setEnabled(false);Volume.setMaximum(Test.volumeMax);Volume.setMinimum(0);Volume.setMaximmLabelString(Integer.toString(Test.volumeMax));Volume.setMinimumLabelString("Volume0");Volume.setValue(0);Lights.setRnabled(false);Lights.setMaximum(Test.lightsMax);Lights.setMinimum(0);Lights.setMaximumLabelString(Integer.toString(Test.lightaMax));Lights.setMinimumLabelString("Lights 0" );Lights.setValue(0);Color.setEnabled(false);Color.setMaximum(Test.colorMax);Color.setMinimum(0);								Color.set MaximumLabellString(Integer.toString(Test.colorMax));Color.setMinimumLabelString("Color0" );Color.setValue(0);Contfast.setEnabled(false);Contrast.setMaximum(Test.contrasMax);Contrast.setMaximum(0);Contrast.setMaximumLabelString(Integer.toString(Test.contrastMax));Contrast.setMinimumLabelString("Contrastrast0" );Contrast.setValue(0);Brightness.setEnabled(false);Brightness.set(Test.brightnessMax);Brightness.set(0) ;Brightness.setMaximumLabelString(Integer.toString(Test.brightnessMax));Brightness.setMinimumLabelString("Brightness0" );Brightness.setValue(0);SoundOff.setState(0);LightsOn.setState(1);SoundOff,setbel("mute");LightsOn.setbel("lights on");PowerOn.setState(0);PowerOn.setLabel("power");tvchannelLabel.setEnabled(false);tvchannelLabel.setFont(new Font("Dialog",0,20));tvchannelLabel.setText("Channel");vcrFunctionLabel.setEnabled(faise);vcrFunctionLabel.setFont(new Font("Dialog",0,20));vcrFunctionLabel.setext("VCR:");vdFunctionLabel.setEnabled(false);dvdFunctionLabel.setFont(nsw Font("Dialog",0,20));dvdFunctionLabel.setText("DVD:" );vcrPauseLabel.setenabled(false);vcrPauseLabel.setFont(Gew Font("Dialog",0,20));vcrPauseLabel.setText("" );dvdPauseLabel.setEnabled(falee);dvdPauseLabel.setFont(new Font("Dialog",0,20));dvdPauseLabel.setText("");vcrChannelLabel.setEnabled(false);vcrChannelLabel.setFont(new Font("Dialog",0,20));vcrChannelLabel.setText("Channel");windowChannelLabel.setEnabled(false);windowChannelLabel.setFont(new Font("Dialog",0,20));windowChannelLabel.setText("PIP:NONE");this.setSize(new Dimension(632,666));TV.add(Volume,new XYConstraints(85,5,-1,-1));TV.add(Lights,new XYConstraints(85,500,-1,-1));TV.add(Color,new XYConstraints(85,55,-1,-1));TV.add(Contrast,new XYConstraints(85,105,-1,-1));TV.add(Brightness,new XYConstraints(85,155,-1,-1));TV.add(Soundoff,new XYConstraints(352,5,-1,-1));TV.add(LightsOn,new XYConstraints(352,500,-1,-1));TV.add(PowerOn,new XYConstraints(352,430,-1,-1));								TV.add(tvchannelLabel,new XYConstraints(22,205,-1,-1));TV.add(vcrFunctionLabel,new XYConstraints(22,258,-1,-1));TV.add(vcrPauseLabel,new XYConstraints(322,258,-1,-1) );TV.add(vcrChannelLabel,new XYConstraints(22,285,-1,-1)) ;TV.add(dvdFunctionLabel,new XYConstraints(22,330,-1,- l) );TV.add(dvdPauseLabel,new XYConstraints(322,330,-1,-1));TV.add(windowChannelLabel,new XYConstraints(22,370,-1,-1));TV.add(jCSeparator1,new XYConstraints(26,250,352,11));TV.add(jCSeparator2,new XYConstraints(26,320,352,11));TV.add(jCSeparator3,new XYConstraints(26,360,352,11));TV.add(jCSeparator4,new XYConstraints(26,400,352,11));TV.add(jCSeparator5,new XYConstraints(2,460,440.40));this.setTitle("Device representation window") ;this.setBounds(100,100,400,550);this.add(TV);this.pack() ;this.toBack();this.show();}}

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号