You are on page 1of 108

Agent Toolkit

by Rebecca Shalfield

Agent Toolkit
The contents of this manual describe the product, Agent Toolkit, and are believed correct at time of going to press. They do not embody a commitment on the part of Logic Programming Associates Ltd (LPA), who may from time to time make changes to the specification of the product, in line with their policy of continual improvement. No part of this manual may be reproduced or transmitted in any form, electronic or mechanical, for any purpose without the prior written agreement of LPA.

Copyright (c) 2004 Logic Programming Associates Ltd.

The Agent Toolkit was written by Z. Meltem ISMIK, Alan Westwood and Brian D. Steel.

Logic Programming Associates Ltd Studio 30 The Royal Victoria Patriotic Building Trinity Road London SW18 3SX England

phone: +44 (0) 20 8871 2016 fax: +44 (0) 20 8874 0449 web: http://www.lpa.co.uk

LPA-PROLOG and WIN-PROLOG are trademarks of LPA Ltd., London England. 19 July, 2004

Contents
AGENT TOOLKIT ................................................................................................................... 2 CONTENTS ........................................................................................................................... 3 CHAPTER 1 - REQUIREMENTS AND INSTALLATION .................................................................. 6 REQUIREMENTS .................................................................................................................... 6 INSTALLATION ...................................................................................................................... 6 FILES YOU SHOULD HAVE ........................................................................................................ 6 CHAPTER 2 THE AGENT LIBRARY ........................................................................................ 7 INTRODUCTION ..................................................................................................................... 7 USING THE AGENT LIBRARY ...................................................................................................... 7 Agents......................................................................................................................... 7 Agent Properties........................................................................................................... 7 What Does An Agent Do? .............................................................................................. 8 Communications .......................................................................................................... 8 Protocol Definitions....................................................................................................... 9 Agent Events................................................................................................................ 9 Running the Agent...................................................................................................... 10 Monitoring Beliefs ....................................................................................................... 11 Examples................................................................................................................... 11 THE PREDICATES ................................................................................................................ 12 agent_reset/0............................................................................................................. 12 agent_create/1 ........................................................................................................... 13 agent_create/2 ........................................................................................................... 14 agent_save/0 ............................................................................................................. 15 agent_save/1 ............................................................................................................. 16 agent_save/2 ............................................................................................................. 17 agent_load/1 .............................................................................................................. 19 agent_initialize/0......................................................................................................... 20 agent_declare/2.......................................................................................................... 22 agent_undeclare/2 ...................................................................................................... 24 agent_declare/5.......................................................................................................... 25 agent_undeclare/5 ...................................................................................................... 27 agent_declare/4.......................................................................................................... 29 agent_assert/1 ........................................................................................................... 31 agent_assert/2 ........................................................................................................... 32 agent_asserta/1.......................................................................................................... 33 agent_retract/1........................................................................................................... 34 agent_retractall/1........................................................................................................ 35 agent_replace/2.......................................................................................................... 36 agent_start/0.............................................................................................................. 38 agent_start/1.............................................................................................................. 39 agent_stop/0.............................................................................................................. 40 agent_post_event/2 .................................................................................................... 41 agent_post_event/3 .................................................................................................... 42 agent_monitored/1 ..................................................................................................... 44 agent_event/3............................................................................................................ 45 agent_id/4 ................................................................................................................. 46 agent_id_det/9 ........................................................................................................... 47 agent_incoming/4....................................................................................................... 49 agent_connected/3..................................................................................................... 51 agUtil_trace /0 ............................................................................................................ 52 agUtil_trace/1 ............................................................................................................. 53

agUtil_msg2term/3 ..................................................................................................... 54 CHAPTER 3 THE KQML LIBRARY ........................................................................................ 55 INTRODUCTION ................................................................................................................... 55 REPRESENTING AND CONVERTING KQML PERFORMATIVES ............................................................... 56 THE PREDICATES ................................................................................................................ 58 kqml_parse_msg/3 ..................................................................................................... 58 kqml_make_msg/3 ..................................................................................................... 60 kqml_is_expression/1 ................................................................................................. 62 kqml_is_performative/1 ............................................................................................... 63 kqml_is_string/1 ......................................................................................................... 64 kqml_is_quotation/1 ................................................................................................... 65 kqml_is_comma_expression/1 ..................................................................................... 66 kqml_is_word/1 .......................................................................................................... 67 kqml_expression/2 ..................................................................................................... 68 kqml_performative/2 ................................................................................................... 70 kqml_string/2 ............................................................................................................. 71 kqml_quotation/2 ....................................................................................................... 72 kqml_comma_expression/2 ......................................................................................... 73 kqml_word/2 .............................................................................................................. 74 APPENDIX A - ARGUMENT TYPE SPECIFICATIONS.................................................................. 75 <arity> ..................................................................................................................... 75 <buffer_identifier> ..................................................................................................... 75 <char_list> ............................................................................................................... 75 <char> ..................................................................................................................... 76 <conjunct_of Type>................................................................................................... 76 <date_time>............................................................................................................. 76 <expr>..................................................................................................................... 76 <file_name> ............................................................................................................. 76 <file_spec>............................................................................................................... 77 <file_specs> ............................................................................................................. 77 <functor> ................................................................................................................. 77 <goal> ..................................................................................................................... 77 <integer_expr> ......................................................................................................... 78 <list_of Type>........................................................................................................... 78 Meta-variables ............................................................................................................ 78 <path_alias>............................................................................................................. 78 <pred_spec> ............................................................................................................ 79 <pred_specs>........................................................................................................... 79 <window_handle> ..................................................................................................... 79 <number> ................................................................................................................ 79 file_search_path/2....................................................................................................... 80 Terms........................................................................................................................ 80 Data Types................................................................................................................. 80 Atom - Data Type ....................................................................................................... 81 Alphanumeric Atoms................................................................................................... 81 Symbolic Atoms ......................................................................................................... 81 Quoted Atoms............................................................................................................ 81 Special Atoms ............................................................................................................ 82 Byte List - Data Type ................................................................................................... 82 Compound Term - Data Type ....................................................................................... 82 Floating Point Number - Data Type................................................................................ 83 Integer - Data Type ..................................................................................................... 84 List - Data Type .......................................................................................................... 84 String - Data Type ....................................................................................................... 84 Variable - Data Type .................................................................................................... 85

APPENDIX B - OVERVIEW OF KQML AGENT EXAMPLES .......................................................... 86 FORWARDING MESSAGES ....................................................................................................... 89 BROADCASTING MESSAGES .................................................................................................... 90 TECHNICAL APPENDIX ........................................................................................................... 91 CONVERSATION POLICY ............................................................................................... 91 PERFORMATIVES......................................................................................................... 91 ERROR ...................................................................................................................... 92 SORRY....................................................................................................................... 93 REGISTER................................................................................................................... 94 IDENTIFY-SELF............................................................................................................. 94 WHOIAM .................................................................................................................... 94 DISCONNECT .............................................................................................................. 95 RECONNECT ............................................................................................................... 95 CONNECTION-ACCEPTED .............................................................................................. 95 LIST-USERS ................................................................................................................ 95 REGISTERED-AGENT .................................................................................................... 96 REQUEST-ADDRESS .................................................................................................... 96 ADDRESS................................................................................................................... 96 FORWARD.................................................................................................................. 97 REPLY ........................................................................................................................ 97 MODIFYING THE FACILITATOR CODE .............................................................................. 97 APPENDIX C OVERVIEW OF STOCKY EXAMPLE ................................................................. 100 INTRODUCTION ................................................................................................................. 100 INTELLIGENT TRADING AGENTS................................................................................................ 100 QUOTE-DRIVEN TRADING ..................................................................................................... 100 STOCK MARKET FACILITATOR ................................................................................................. 101 MARKET MAKER AGENTS ...................................................................................................... 102 Exercise 1................................................................................................................ 105 TRADING SESSIONS ........................................................................................................... 105 KNOWBOT MARKET MAKERS .................................................................................................. 106 Exercise 2................................................................................................................ 106 INDEX.............................................................................................................................. 108

Chapter 1 - Requirements And Installation


Requirements
To use the WIN-PROLOG TCP/IP and Agent Toolkits, you will need the following: Windows 98/NT/ME/2000/XP Operating System installed. TCP/IP Protocol and a suitable adapter installed. The dynamic link library file Ws2_32.dll or Wsock32.dll. These are a standard part of Windows operating systems, and should already be in your Windows directory. If you have a different DLL or want to use your own see the section Using Other DLLs. A copy of WIN-PROLOG 4.500 or later installed.

Installation
To install the WIN-PROLOG TCP/IP and Agent Toolkits from the LPA WIN-PROLOG CD-ROM, just tick the appropriate checkboxes during installation.

Files You Should Have


Filename tcp.pc http.pc mail.pc agent.pc Description TCP/IP Sockets Library object file HTTP Client Library object file EMAIL Library object file Agent Library object file

agdefpro.pl Default agent protocol file kqml.pc KQML Library object file

Chapter 2 The Agent Library


Introduction
The definition of a software agent is somewhat a controversial issue. But many people agree that they are software that exhibit at least some or all of the following characteristics: Autonomy, agents do not require constant human user intervention Awareness, agents are aware of their environment and react to the changes in it Persistence, agents function continuously for a period of time rather than performing an action and disappearing when it is done. Adaptiveness, agents adapt their behaviour over time and may learn to respond to the changes in the environment better. Cooperation, agents are aware of and communicate with other agents to achieve their goals.

The Agent Library allows you to experiment with writing programs with the above characteristics, it does not impose any agent architecture, conversation policy or an agent communication language. This makes it flexible and suitable for prototyping and because your agents are written in Prolog, they can easily use many Artificial Intelligence and Logic Programming techniques. The Agent Library mainly gives you a skeleton of an agent which can exhibit autonomy, awareness, persistence, cooperation and adaptiveness and makes it easy for you to experiment with implementing those characteristics. The example agents provided with this release illustrate the use of the agent library features, agent communication in Prolog and KQML.

Using the Agent Library


Agents
As far as this library is concerned, an agent is a program that communicates with other agents and responds to the agent events. These events may be generated by the agent library, the user or the agent itself. This toolkit views each agent as an independent software entity, so only one agent per instance of Prolog is allowed.

Agent Properties

AN AGENT HAS a long term goal

REPRESENTED BY the main purpose of the agent program, i.e. to maintain a database, to collect data, to provide services for other agents etc. asserted facts events posted by the agent events posted by the system event handler declarations, e.g.. if event A happens, it must trigger the execution of plan B and all its alternatives. event handlers that describe how to achieve the short term goals; each plan can have many alternatives, expressed as alternative clauses of the event handlers.

beliefs (its knowledge) events that it responds to short term goals

plans

What Does An Agent Do?


When an agents starts it waits until an agent event happens. When an event happens it decides what to do by looking through its plans and executes all the alternatives until the goal has been achieved (the event has been handled) or there are no more plans to try.

Communications
All communications are managed according to the predicates defined in the protocol definition files. Incoming Connection Requests Every agent runs a server which listens for incoming connection requests from other programs. This server starts operating when the agent is initialized and uses the protocol specified when the agent was created (primary protocol). The agent can operate several servers simultaneously, all using the same or different protocols. These protocols can be user defined or supplied with the Agent Toolkit. Connecting to other agents An agent can connect to other agents using the predicates defined in its protocol definition file/s. For example, the standard protocol called default defines the predicates agent_connect/3 and agent_disconnect/1 and keeps a database of currently active connections (agent_connected/3). It also generates the communication related agent events like connected, connection_accepted, connection_closed, cannot_connect, etc.

Sending and Receiving Messages An agent sends and receives messages using the predicates defined in its protocol definition file. For example, the standard protocol called default defines the predicates agent_send/2 for sending messages and the socket event handler ag_SockHandler/3 for receiving incoming messages and accepting connection requests. It also keeps a database of the incoming messages (agent_incoming/4) and generates the agent event incoming_msg whenever an incoming message is received.

Protocol Definitions
Every agent must declare, define and use at least one protocol. The name of this protocol will appear in its full name or URL (primary protocol). Although an agent can operate on several ports using a different protocol for each, only the primary protocol will be included in its Agent Toolkit record (see agent_create/1 and agent_id_det/9). The agent uses the protocol called default if no other is declared and defined. All agent protocols are defined in protocol definition files. These files are regular Prolog source code files which define the predicates the agent will be using to manage its communications. These predicates are normally defined using the TCP/IP library predicates and specify how the agent communicates with other agents/programs and generate the agent events related to communications. Currently two protocols are defined, default and simple. Defining additional protocols and/or modifying the existing ones is easy, just change the source code of the existing protocol files (agdefpro.pl and agsimpro.pl). To add a new protocol: Define predicates for: o Connecting to another agent, (e.g. my_agent_connect/3) o Disconnecting, (e.g. my_agent_disconnect/1) o Sending data, (e.g. my_agent_send/2) o Handling socket events (accept, read, closed), (e.g. my_ag_SockHandler/3) Declare this protocol with agent_declare/4 or agent_declare/5.

Agent Events
Agent events are POSTED when they are sensed either by the agent library or the agent itself.

The Agent Library gives you full access to the agent event queue, so an agent can postpone an event if it wants to handle it later or can remove, ignore, modify any event as required. When an agent event happens, the Agent Library will look for a plan to handle this event (declared by the predicate agent_declare/2). If no plans were declared for this event or none of the alternatives can successfully handle the event then a cannot_handle_event event will be generated. If this event cannot be handled either, it will be ignored. The following events are normally posted by the agent library using the default protocol: cannot_handle_event agent_stop connection_closed cannot_send incoming_msg cannot_connect connected connection_accepted changed_monitored none of the plans worked stop the agent's execution a connection has been closed cannot send a message incoming message cannot connect connection established connection request accepted a monitored belief is changed

Some of those should be handled, if no handlers are specified by the agent, the default handlers will be used (Most of the default handlers safely ignore the event).

Running the Agent


Running an agent written with the Agent Library is a four step process: Step 1: Create the agent Creating an agent means creating a record for the agent containing its name, the communication protocol it uses etc. This is accomplished by using one of the predicates prefixed with agent_create. Step 2: Make declarations Agent declarations inform the system of the agent's short term goals, plans and other activities. The most important declarations are the event handler declarations which set out the actions to be taken when responding to agent events. Other than event handlers, an agent can also declare monitored beliefs 10

and communication protocols. All agent declarations are done by calling the predicates prefixed with agent_declare. Step 3: Initialize the agent Initializing the agent starts the communications and socket operations for the agent using the specified protocol. Agents are initialized by the predicate agent_initialize/0. Step 4: Start the agent The predicates prefixed with agent_start begin running the agent by starting the main agent event loop.

Monitoring Beliefs
Monitoring the agents beliefs enable the agent to take action whenever a certain piece of interesting data is updated (e.g. current_status(connected), known_agents(simon,sally,agent009) etc.). Monitored beliefs are first declared by the agent_declare/2 predicate and updated by using one of the agent_assert, agent_retract, agent_replace predicates. Whenever any one of the monitored beliefs change, the agent toolkit posts a changed_monitored event. This event is handled just like any other agent event by proving and declaring a handler.

Examples
The Agent Library examples are presented in three directories called test, prolog and kqml. The examples in the test directory are exercises in using the agent library features (using the default and simple protocols, monitoring beliefs etc.) The directory called prolog contains two fully functional agents. One of these agents called 'Simon' maintains a database and the other one called 'Sally' can query and modify this database from remote locations. Simon and Sally communicate by exchanging messages expressed in Prolog over the Internet. The kqml directory contains an example framework for agents which communicate in KQML. It features a facilitator agent which provides forward, broadcast and recommend services between registered client agents.

11

The Predicates
agent_reset/0
reset the agent library agent_reset Comments Resets the agent toolkit. All active connections are shut off, all agent records and declarations are deleted and the agent event queue is reset. Examples The example below resets the agent toolkit: ?- agent_reset. <enter> yes Notes This predicate is normally used at the beginning of an agent's code to clean up the memory before creating, initializing and starting the agent. It does not stop the agent toolkit main event loop. agent_start/0

See also

12

agent_create/1
create an agent record agent_create( AgentID ) ?AgentID <atom> or <variable>

Comments This predicate creates an agent record with default parameters. If there is a previously created agent record (i.e. one of the agent_create predicates has been called before), it will be overwritten. If AgentID is unbound, then an ID will be automatically generated, otherwise the value of AgentID will be used. Examples The following example creates an agent record with the default parameters and calls agent_id_det / 9 to check the new agent's details: ?- agent_create(AgentID). <enter> AgentID = agent032F085F ?- agent_id_det(ID,N,Pr,H,P,T,U,F,D). <enter> ID = agent032F085F , N = name("agent") , Pr = protocol(default) , H = host(_38014) , P = port(_38018) , T = target("agent" ) , U = url(_38026) , F = full_name(_38030) , D = data('032F085F.dat') Notes The agent will have the following default parameters: name('agent') protocol('default') port (P) % P is dynamically assigned target("agent") The rest of the agent record is filled in when the agent is initialized. See also agent create/2 agent initialize/0 agent_id_det/9

13

agent_create/2
create an agent record agent_create( Params, AgentID ) +Params ?AgentID <list> <atom> or <variable>

Comments This predicate creates an agent record with the given parameters and returns the ID of the newly created agent. If there is a previously created agent record (i.e. one of the agent_create predicates has been called before), it will be overwritten. If Params is an empty list, then the agent will have the following default parameters: name('agent') protocol('default') port (P) % dynamically assigned target(`agent`) Params can also be a list containing some or all of the tuples below which set the agent parameters: name (Name) protocol (Protocol) port (P) target(Target) If AgentID is unbound, then an ID will be automatically generated, otherwise the value of AgentID will be used. Examples The example below creates an agent called 'MyAgent' which will use the simple protocol as its primary protocol (all other parameters will be set to defaults): ?- agent_create( [ name('MyAgent'), protocol(simple) ], ID). <enter> ID = 'MyAgent037FFC52' Notes See also Params must be ground. agent create/0 agent id det/9

14

agent_save/0
save agent info agent_save Comments This predicate saves the agent's details and declarations to the agent's data file. The name of this file is automatically assigned and can be accessed by the Prolog fact agent_id_det/9. The example below first checks the agent's details and saves them: ?- listing(agent_id_det). <enter> % agent_id_det/9 agent_id_det( simon029BD3DE, name(`simon`), protocol(default) , host(`melly`) , port (1043), target (`simor` ) , url('default://melly:1043/simon'), full_name('simon029BD3DE@default://melly:1043 /simon'), data('02 9BD3DE.dat') ). yes ?- agent_save. <enter> yes Notes If the file already exists, it is overwritten otherwise it is created. When the agent is saved using the agent_save predicates, the additional protocols are not saved. You must declare these again after loading the agent back. Saving and loading the agent details allow you to maintain continuity during the agent's lifetime. The current state of the agent is not saved by the system but by using agent_save/2 you can save any relevant predicates which describe the agent's current state. See also agent save/1 agent save/2 agent_load/l agent declare/5 agent id det/9

Examples

15

agent_save/1
save agent info agent_save( File ) +File Comments Examples <file name>

This predicate saves the agent's details and declarations to the specified file. The example below first saves the agent's details and declarations to a file called ' myagent. dat' in the current directory: ?- agent_save( 'myagent.dat' ). <enter> yes

Notes

If the file already exists, it is overwritten otherwise it is created. When the agent is saved using the agent_save predicates, the additional protocols are not saved. You must declare these again after loading the agent back. Saving and loading the agent details allow you to maintain continuity during the agent's lifetime. The current state of the agent is not saved by the system but by using agent_save/2 you can save any relevant predicates which describe the agent's current state.

See also

agent save/0 agent save/2 agent load/1 agent_declare/5 agent id det/9

16

agent_save/2
save agent info agent_save( File, UserPreds ) +File +UserPreds <file name> <list>

Comments This predicate is similar to agent_save/1 but it also saves the specified predicates. File is the file name where the agent record and the specified predicates will be saved. UserPreds is a list of predicate specifications of the form: [Functorl/Arityl, Functor2/Arity2,..] where Functor is an atom that is the functor of the predicate and Arity is an integer that specifies the number of arguments of the predicate. Examples The example below first saves the agent's details and declarations to a file called ' myagent.dat' along with the predicates my_data/3 and my_predicates/4: ?- agent_save('myagent.dat', [my_data/3, my_predicates/3] ). <enter> yes Notes UserPreds must be ground. If the file already exists, it is overwritten otherwise automatically created. When the agent is saved using the agent_save predicates, the additional protocols are not saved. You must declare these again after loading the agent back. Saving and loading the agent details allow you to maintain continuity during the agent's lifetime. The current state of the agent is not saved by the system but by using agent_save/2 you can save any relevant predicates which describe the agent's current state. See also agent_save/0 agent save/1 agent load/1 agent declare/5

17

agent id det/9

18

agent_load/1
load previously saved agent info agent_load( File ) +File <file name>

Comments This predicate is used for loading agent data previously saved by using one of the agent_save predicates. File is the name of the file containing the agent information. Examples The example below loads all the saved agent information from a file called 'myagent.dat': ?- agent_load('myagent.dat'). <enter> # 0.01 seconds to consult myagent.dat [c:\agents\] yes Notes If you load a Prolog file and then load another file with the same name but a different extension then WIN-PROLOG abolishes the first Prolog file. So, make sure the names you give to the source code file of your agent and the saved agent files are different. When the agent is saved using the agent_save predicates, the additional protocols are not saved. You must declare these again after loading the agent back. See also agent save/0 agent save/1 agent_save/2 agent declare/5

19

agent_initialize/0
initialize the agent agent_initialize Comments This predicate initializes the agent by creating a server process and filling in the rest of the agent details which are kept in agent_id_det/9 structure. The server process created here listens for the incoming connection requests and accepts them according to the specifications of the primary protocol. Examples The following example first creates an agent and then initializes it. agent_id_det/9 is displayed before and after the initialization to show the difference: ?- agent_create(_). <enter> yes ?- agent_id_det(ID,N,Po,H,Pt,T,URL,FN,F). <enter> ID = agent039195BB , N = name(`agent`) , Po = protocol(default) , H = host(_27694) , %uninstantiated for now Pt = port(_27698) , %uninstantiated for now T = target(`agent`) , URL = url(_27706) , %uninstantiated for now FN = full_name(_27710) ,%uninstantiated for now F = data('039195BB.dat') ?- agent_initialize. <enter> yes ?- agent_id_det(ID,N,Po,H,Pt,T,URL,FN,F). <enter> ID = agent039195BB , N = name(`agent`) , Po = protocol(default) , H = host(`melly`) , Pt = port(1056) , T = target(`agent`) , URL = url('default://melly:1056/agent') , FN = full_name( 'agent039195BB@default://melly:1056/agent' ) , F = data('039195BB.dat') Notes The agent must have been created or loaded before it can be initialized (i.e. an agent record must exist). If you are not using the default protocol as the primary protocol, you 20

must declare a primary protocol with agent_declare/4 before initializing the agent. See also agent_create/l agent load/1 agent declare/4 agent id det/9 Protocol Definitions

21

agent_declare/2
declare agent event handlers and monitored beliefs agent_declare( ToDeclare, Declarations ) +ToDeclare +Declarations <atom> <list>

Comments This predicate is used for declaring the agent event handlers and the monitored beliefs. ToDeclare signals the type of the declaration and it must be either the atom 'handlers' (for event handler declarations) or the atom 'monitored' (for monitored belief declarations). If ToDeclare is the atom 'handlers' then Declarations must be a list of the form: [ (EventNamel, HandlerNamel), (EventName2,HandlerName2),..] If ToDeclare is the atom 'monitored' then Declarations must be a list of the form: [ Functorl(Arg11,Argl2..), Functor2(Arg21,Arg22,..),..] Examples The example below declares that the event ' incoming_msg' will be handled by the predicate handle_msg/3: ?- agent_declare(handlers,[(incoming_msg, handle_msg)]). <enter> yes The example below declares multiple event handlers: ?- HandlerList = [(incoming_msg, my_msg_handler), (cannot_send, my_msg_handler), (cannot_connect, my_msg_handler), (my_start, my_start_handler), (my_stop, my_stop_handler)], agent_declare( handlers, HandlerList). <enter> The example below declares multiple agent beliefs to be monitored: ?- ToMonitor = [ my_state(_,_), other_agents(_,_,_), done(cleanup) ], agent_declare(monitored, ToMonitor). <enter>

22

Notes

agent_declare/2 will succeed even if the given agent event handlers are currently undefined; they are only executed when the corresponding event occurs. This allows you to declare or undeclare agent event handlers and monitored beliefs at any time during the agent's execution and change the agent's behaviour dynamically during its lifetime. agent undeclare/2 agent declare/4 agent declare/5 Agent Events Monitoring Beliefs

See also

23

agent_undeclare/2
undeclare agent event handlers and monitored beliefs agent_undeclare( ToUnDeclare, Declarations ) +ToUnDeclare +Declarations <atom> <list>

Comments This predicate is used for undoing the agent event handler and the monitored belief declarations. ToUnDeclare signals the type of the declaration to be undone. It must be either the atom 'handlers' (for undoing the event handler declarations) or the atom 'monitored' (for undoing the monitored belief declarations). If ToUnDeclare is the atom 'handlers' then Declarations must be a list of the form: [ (EventNamel, HandlerNamel), (EventName2,HandlerName2),..] If ToUnDeclare is the atom 'monitored' then Declarations must be a list of the form: [ Functorl(Argil,Argl2..), Functor2(Arg21,Arg22,..),..] Examples The example below undeclares multiple event handlers: ?- HandlerList= [ (incoming_msg, my_msg_handler), (cannot_send, my_msg_handler) , (cannot_connect, my_msg_handler), (my_start, my_start_handler) , (my_stop, my_stop_handler) ] , agent_undeclare( handlers, HandlerList ). <enter> The example below undeclares multiple agent beliefs: ?- Beliefs = [ my_state(_,_), other_agents(_,_,_) , done(cleanup) ], agent_undeclare(monitored, Beliefs). <enter> Notes agent_undeclare/2 will succeed even if the second argument corresponds to handlers or beliefs that have not been declared before. agent declare/2

See also 24

agent_declare/5
declare an additional agent protocol agent_declare( protocol, Name, Mode, Handler, Port ) protocol +Name +Mode <atom> <atom> <conjunction>

+Handler <atom> ?Port <integer> or <variable>

Comments This predicate is used for declaring a user defined protocol to manage the agent communications in addition to the primary protocol. Defining additional protocols allows your agent to talk to several agents using different protocols for each connection. The first argument must be the atom 'protocol', which signals the declaration of a protocol. Name is an atom giving the name of the protocol. For the default protocol this is the atom 'default'. Mode is a TCP Library <mode term> of the form (Delimiter, Mode, Type ), specifying the send and receive mode parameters. For the default protocol, this is set to (`aaa`, any, var). Handler is an atom specifying the TCP/IP library socket event handler. This handler is used for creating a socket callback for the agent and it must have been defined before. For the default protocol it corresponds to the term ag_SockHandler (_, _, _). Port is an integer where the listener (server) for this protocol will be listening at. If Port is a variable then a port number will be automatically assigned and returned. Examples The example below declares a user defined protocol called my_protocol to operate on port 5000: ?- agent_declare( protocol, my_protocol, (`any`,var), my_protocol_handler(_,_,_) , 5000 ). <enter> yes

25

Notes

Unlike agent_declare/4, agent_declare/5 can be used at any time during the agent's execution. When the agent is saved using the agent_save predicates, the additional protocols are not saved. You must declare these again after loading the agent back. The easiest way to define your own protocols is to modify the existing ones accordingly. The default protocol is defined in the agent toolkit file ' agdefpro.pl' and an example protocol called 'simple' is defined in the file ' agsimpro.pl',

See also

agent_undeclare/5 agent declare/4 agent declare/2 agent_save/0 agent load/1 Protocol Definitions

26

agent_undeclare/5
undeclare an additional agent protocol agent_undeclare( protocol, Name, Mode, Handler, Port ) protocol +Name ?Mode ?Handler ?Port <atom> <atom> <conjunction> or <variable> <atom> or <variable> <integer> or <variable> p

Comments This predicate is used for undoing an additional protocol declaration. As a result, all connections using this protocol and its server process is killed. The first argument must be the atom 'protocol', which signals the declaration of a protocol. Name is an atom giving the name of the protocol. For the default protocol this is the atom ' default'. Mode is a TCP Library <mode term> of the form (Delimiter,Mode,Type), specifying the send and receive mode parameters. For the default protocol, this is set to (`aaa`, any, var). Handler is an atom specifying the TCP/IP library socket event handler. This handler is used for creating a socket callback for the agent and it must have been defined before. For the default protocol it corresponds to the term ag_SockHandler (_, _, _). Port is an integer where the listener (server) for this protocol will be listening at. If Port is a variable then a port number will be automatically assigned and returned. Examples The example below undeclares a user defined protocol called my_protocol: ?- agent_declare( protocol, my_protocol, Mode, Handler, Port ). <enter> Mode = (``,any,var) , Handler = my_protocol_handler(_4052,_4054,_4056) , Port = 5000

27

Notes

Unlike agent_declare/4, agent_declare/5 can be used at any time during the agent's execution. When the agent is saved using the agent_save predicates, the additional protocols are not saved. You must declare these again after loading the agent back. The easiest way to define your own protocols is to modify the existing ones accordingly. The default protocol is defined in the agent toolkit file 'agdefpro.pl' and an example protocol called 'simple' is defined in the file 'agsimpro.pl'.

See also

agent declare/5 agent declare/4 agent_save/0 agent_load/l Protocol Definitions

28

agent_declare/4
declare the primary agent protocol agent_declare( protocol, Name, Mode, Handler ) protocol +Name +Mode Handler <atom> <atom> <@argument +Handler> <atom>

Comments This predicate is used for declaring the primary protocol, changing the name of the default primary protocol or assigning a user defined protocol as the primary protocol. The first argument must be the atom 'protocol', which signals the declaration of a protocol. Name is an atom giving the name of the protocol. For the default protocol this is the atom ' default'. Mode is a TCP Library <mode term> of the form (Delimiter, Mode, Type ), specifying the send and receive mode parameters. For the default protocol, this is set to (`aaa`, any, var). Handler is an atom specifying the TCP/IP library socket event handler. This handler is used for creating a socket callback for the agent and it must have been defined before. For the default protocol it corresponds to the term ag_SockHandler(_,_,_). Examples The example below declares a user defined protocol called my_protocol as the primary protocol. After the agent is initialized, this protocol will appear in its full name as shown below: ?- agent_reset, agent_declare( protocol, my_protocol, (``, any, var) , my_protocol_handler(_,_,_) ), agent_create( [protocol(my_protocol) ], ID ), agent_initialize, listing(agent_id). <enter> % agent_id/4 agent_id( agent024CEDEB, `agent`, `'my_protocol://melly:1044/agent'` , 'agent024CEDEB@my_protocol://melly:1044/agent'` ID = agent024CEDEB Notes 29 The primary protocol is the protocol that is used by the agent at the

host and port which appears in its full name. Although an agent can operate on several ports using different protocols simultaneously, only the primary protocol will be included in its full name. The listener for the primary protocol which accepts the incoming connection requests is created when the agent is initialized. Unlike the additional protocols, the primary protocol cannot be undeclared during the agent's execution. The agent will use the default protocol as its primary protocol if one is not declared. To change the name of the default protocol, use agent_declare/4 with the Mode and Handler values of the default protocol. See also agent declare/5 agent undeclare/5 Protocol Definitions

30

agent_assert/1
assert a monitored agent belief agent_assert( Belief ) +Belief <clause>

Comments This predicate is used for asserting a monitored agent belief. If Belief is being monitored, this predicate will generate the agent event (changed_monitored, (assert, Belief) ) after asserting the value of Belief. Otherwise it will work the same way as the regular assert/1. Examples The example below adds a clause to the agent's database: ?- agent_assert( my_state(normal) ). <enter> See also agent assert/2 agent declare/2 Monitoring Beliefs

31

agent_assert/2
assert a monitored agent belief agent_assert( Belief, Pos ) +Belief +Pos <clause> <integer>

Comments This predicate is used for asserting a monitored agent belief at the specified position in its sequence of existing clauses. If Belief is being monitored, this predicate will generate the agent event: (changed_monitored, (assert, Belief) ) after asserting the value of Belief. Otherwise it will work the same way as the regular assert/2. Examples The examples below add clauses to the agent's database: ?- %Add it to the end agent_assert( my_state(normal),0 ). <enter> ?- %Add it to the top agent_assert( my_state(confused),1 ). <enter> ?- %Add it at the 3rd position agent_assert( my_state(connected) , 3 ). <enter> See also agent assert/1 agent declare/2 Monitoring Beliefs

32

agent_asserta/1
assert a monitored agent belief at the top agent_asserta( Belief ) +Belief <clause>

Comments This predicate is used for asserting a monitored agent belief at the top of its sequence of existing clauses. If Beliefs being monitored, this predicate will generate the agent event (changed_monitored, (assert, Belief)) after asserting the value of Belief. Otherwise it will work the same way as the regular asserta/1. Examples The example below adds a clause at the top of the agent database: ?- agent_asserta( my_state(normal) ). <enter> See also agent declare/2 agent assert/1 agent assert/2 agent_retract/l agent replace/2 Monitoring Beliefs

33

agent_retract/1
retract a monitored agent belief agent_retract( Belief ) +Belief <clause>

Comments This predicate is used for retracting a monitored agent belief. If Belief is being monitored, this predicate will generate the agent event (changed_monitored, (retract, Belief) ) after retracting the value of Belief. Otherwise it will work the same way as the regular retract /1. Examples The example below retracts a clause from the agent database: ?- agent_retract( my_state(normal) ). <enter> See also agent_declare/2 agent assert/1 agent assert/2 agent retractall/1 agent replace/2 Monitoring Beliefs

34

agent_retractall/1
retract all matching monitored agent beliefs agent_retractall( Belief ) +Belief <clause>

Comments This predicate is used for retracting all monitored agent beliefs matching its argument. If Belief is being monitored, this predicate will generate the agent event: (changed_monitored, (retractall, Belief) ) after retracting the value of Belief. Otherwise it will work the same way as the regular retractall/1. Examples The example below retracts all clauses of my_state/1 from the agent database: ?- agent_retractall( my_state(_) ). <enter> See also agent_declare/2 agent assert/1 agent assert/2 agent retract/1 agent replace/2 Monitoring Beliefs

35

agent_replace/2
change a monitored agent belief agent_replace( OldBelief, NewBelief ) +0ldBelief +NewBelief <clause> <clause>

Comments This predicate is used for changing monitored agent beliefs. All the matching values of OldBelief are retracted and the value of the NewBelief is asserted. If OldBelief is being monitored, this predicate will generate the agent event: (changed_monitored, (replace, (OldBelief,NewBelief) ) ). If NewBelief is being monitored, this predicate will generate the agent event: (changed_monitored, (assert, (NewBelief) ) ) . If OIdBelief and/or NewBelief is not being monitored, then the behaviour of this predicate will be the same as the following: retractall(OldBelief) , assert(NewBelief). Examples The example below updates an agent's state by replacing the clause my_state (normal) with my_state(confused): ?- agent_replace( my_state(normal), my_state(confused) ). <enter> yes If my_state(X) is being monitored, then the following agent events will be generated: changed_monitored,(replace,my_state(normal),my_s tate(confused)) changed_monitored,(assert,my_state(confused)) If however only my_state(normal) is being monitored, then only the following agent event will be generated: changed_monitored,(replace,my_state(normal),my_s

36

tate(confused)) If only my_state(confused) is being monitored, then only the following agent event will be generated: changed_monitored,(assert,my_state(confused)) See also agent declare/2 agent_assert/l agent assert/2 agent retract/1 Monitoring Beliefs

37

agent_start/0
start the agent agent_start Comments This predicate is used for starting the agent. When agent_start/0 is called, the agent toolkit enters its main event loop and starts processing the agent events. Any other predicate calls made after this one will not be processed until after the agent has been stopped. To stop the agent, an agent_stop event must be posted either directly by the agent or as a consequence of other events. Examples The following example first creates and initializes an agent with all the default parameters and then posts an agent_stop event to cause the agent to stop immediately after it starts: ?- agent_create(ID), agent_initialize, agent_post_event(agent_stop,_) agent_start. <enter> ID = agent033290A4 Notes See also The agent must have been created, initialized and all the necessary declarations must have been made before this predicate is called. agent_start/l agent create/1 agent initialize/0 agent stop/0 agent reset/0 Agent Events

38

agent_start/1
start the agent agent_start(Interval) +Interval <floating point number>

Comments This predicate starts the agent and tells the system to check the agent events every Interval seconds. This predicate is normally used for testing purposes, because it leaves the Prolog console free to execute any other commands (i.e. for putting spy points on certain predicates, checking the program listing etc.). Examples The following example starts the agent with the Interval value of 0.2 seconds: ?- agent_start(0.2). <enter> yes Notes The bigger the value of Interval, the slower the agent will run. The most comfortable value for Interval varies from computer to computer and the best way to find out a suitable value will be to experiment with it using different values. The agent must have been created, initialized and all the necessary declarations must have been made before calling this predicate. See also agent_start/0 agent create/1 agent initialize/0 agent stop/0 agent reset/0 Agent Events

39

agent_stop/0
stop the agent agent_stop Comments This predicate posts an agent_stop event and stops the main agent event loop. It is effectively defined as follows: agent_stop :agent_post_event( agent_stop, _ ). Examples The following code defines a predicate for stopping the agent at the given absolute time (using the TCP/IP library timer callbacks): stop_agent_at( Hour, Minute, Secs ) :Goal = agent_stop, tcp_daily( Hour, Minute, Secs, Time ), tcp_create_timer_callback( Time, Goal, _ ). ?- stop_agent_at(14,54,00). <enter> yes Notes See also This predicate is useful mostly when experimenting with the agent toolkit from the Prolog command line. agent start/0 Agent Events

40

agent_post_event/2
generate an agent event agent_post_event( Event, Params ) +Event +Params <atom> <conjunction>

Comments This predicate is used to generate an agent event with the given name and parameters. Event is an atom giving the name of the agent event to be generated. Params is an optional Prolog term specifying the parameters of the agent event generated. The agent event generated with this predicate will be added at the end of the agent event queue. Examples The following generates an event called ' connection_request ' with two parameters: ?- agent_post_event( connection_request, ( from_agent (simon) , type( 'database_agent' ) ). <enter> yes The following command will stop the agent's execution by generating an 'agent_stop' event: ?- agent_post_event(agent_stop,_). <enter> yes See also agent post event/3 agent event/3 agent stop/0 Agent Events

41

agent_post_event/3
generate an agent event agent_post_event( Pos, Event, Params ) +Pos +Event +Params <integer> or <atom> <atom> <conjunction>

Comments This predicate generates an agent event with the given name and parameters and places it in the agent's event queue at the specified position. Pos is an atom or an integer that signals the position of the event within the event queue. If Pos is the atom ' urgent' then Event will be placed at the top of the queue, If Pos is the atom ' end' then Event will be placed at the end of the queue. If Pos is an integer then Event is inserted at the given position relative to the beginning. Event is an atom giving the name of the agent event to be generated. Params is an optional Prolog term specifying the parameters of the agent event generated. The agent event generated with this predicate will be added at the end of the agent event queue. Examples The following generates an event called 'connection_request' with two parameters and places it at the end of the event queue: ?- agent_post_event( end,connection_request, ( from_agent(simon) ,type( 'database_agent' ) ) ). <enter> yes The following command will stop the agent's execution by generating an ' agent_stop ' event and placing it in front of all the other events: ?- agent_post_event(urgent, agent_stop, _). <enter> yes The following command will generate and insert the event ' check_connection ' as the second event in the queue: ?- agent_post_event( 2, check_connection, 42

con_no(12) ). <enter> See also agent post event/2 agent event/3 Agent Events

43

agent_monitored/1
get the list of all the monitored beliefs agent_monitored( Beliefs ) -Beliefs <list>

Comments This predicate returns a list of all the agent beliefs that are currently being monitored. Examples The following illustrates the use of agent_monitored/1: ?- agent_monitored(Beliefs). <enter> Beliefs = [my_state(_,_), my_connections(_)] See also agent declare/2 Monitoring Beliefs

44

agent_event/3
store/access agent events agent_event( EventID, ?EventID ?Event ?Params <integer> <atom> <term> E

Comments This is a dynamic predicate which is used for storing and accessing all the agent events. EventID is an integer that uniquely identifies an event. Event is the name of the agent event. Params can be any Prolog term and it holds additional information about this event. Examples The following code defines utilities using agent_event/3: reset_event_queue :retractall( agent_event(_,_,_) ). ignore_event(Event) :retract( agent_event(Event,_,_) ). get_all_events(AllEvents) :findall( events(ID, E, P), agent_event( ID, E, P ), AllEvents ). Notes See also This predicate gives you complete and unlimited access to the agent's event queue. agent_post_event/2

45

agent_id/4
store/access agent info agent_id( ID, ?ID ?Name ?URL ?FullName <atom> <string> <string> <string> N

Comments This is a dynamic predicate which is used for storing and accessing the information maintained about the agent. ID is an atom used to identify the agent. Name is the name of the agent. URL is the location of the agent, given as follows: Protocol://Host:Port/Target FullName holds the agent's name and URL together as follows: Name@Protocol://Host:Port/ Target Examples The following code displays agent_id/4 for an agent called fred which is running on a computer called melly: ?- agent_id(ID, Name, URL, FullName). <enter> ID = fred02955C76 , Name = `fred` , URL = `'default://melly:1046/fred'` , FullName = `'fred02955C76@default://melly:1046/fred'` Notes This predicate is useful when you need to access the agent contact information as strings. This predicate is only available after the agent has been initialized. See also agent id det/9 agent_initialize/0

46

agent_id_det/9
store/access agent info agent_id_det( ID, N, Po, H, Pt, T,URL, FN, D ) ?ID ?N ?Po ?H ?Pt ?T ?URL ?FN ?D <atom> <compound term> <compound term> <compound term> <compound term> <compound term> <compound term> <compound term> <compound term>

Comments This is a dynamic predicate which is used for storing and accessing detailed information maintained about the agent. ID is an atom used to identify the agent. The argument of N holds the name of the agent as a string: name (TheName) The argument of Po holds the name of the agent's default protocol as an atom: protocol (TheProtocol) The argument of H holds the name of the computer , where the agent is running (a string): host(TheHost) The argument of Pt holds the port number where the agent's server is listening at (an integer): port(ThePort) The argument of T holds additional location information (a string):

47

target(TheTarget) The argument of URL holds the location of the agent (an atom): url(TheURL) where TheURL has the form, Protocol: / /Host: Port /Target The argument of FN holds the agent's name and URL together as a single atom: full_name(TheFullName) where TheFullName has the form: Name@protocol://Host:Port/Target The argument of D holds the name of a disk file used when saving the agent (an atom): data(Data) Examples The following code displays agent_id_det/9 for an agent called fred which is running on a computer called melly: ?- agent_id_det(ID,N,Po,H,Pt,T,URL,FN,D). <enter> ID = agent039195BB , N = name(`fred`), Po = protocol(default) , H = host(`melly`) , Pt = port(1056) , T = target(`agent`) , URL = url('default://melly:1056/agent') , FN = full_name('fred@default://melly:1056/agent') , D = data('039195BB.dat') Notes This predicate is useful when you need to access any of the agent information individually. The terms Host, Port, URL, and FullName will only be available after the agent is initialized. See also agent id/4 agent save/0 agent initialize/0

48

agent_incoming/4
store/access incoming messages agent_incoming( MesNo, Socket, Message, Params ) ?MesNo ?Socket ?Message ?Params <integer> <integer> <string> <term>

Comments This is a dynamic predicate which is used for storing and accessing all the incoming messages received by the default protocol. MesNo is an automatically generated number which identifies the message. Socket is an integer which identifies the socket connection where this message has been received from. Message is a string which holds the message received. Params can be any Prolog term which holds any other information necessary, it is not used by the default protocol at present. Examples The following code defines a simple handler which reports all the incoming messages: my_msg_handler( incoming_msg, (MesNo,Connection) ) :agent_incoming( MesNo, Connection, MsgStr, _ ), nl, write( `I have got an incoming message:`), nl, write( MesNo - MsgStr ), retractall( agent_incoming(MesNo,_,_,_)). Notes This predicate is only available if you are using the default protocol as the primary protocol. agent_incoming/4 is useful when writing your own additional protocols. For example, whenever a new message is received by the agent, the default protocol first gives it a number and stores it using this structure, then posts an incoming_msg event. This particular message is then accessed and handled using the agent_incoming/4 structure. 49

It is important to remember to delete the incoming messages after they have been handled, otherwise it might cause you to run out of memory. See also agent_id/4 agent connected/3 agent event/3 Agent Events Protocol Definitions Communications

50

agent_connected/3
store/access the agent's currently active connections agent_connected( Type, Conn, Proto ) ?Type ?Conn ?Proto <atom> <integer> <atom>

Comments This predicate is used for storing and accessing the currently active connections of the agent. Type is an atom which holds the category of connection. Under the default protocol, there are currently 3 categories: accepted (accepted connection requests from other agents), client (connections established and initiated by this agent), listener (the listener socket for a protocol) Conn is the socket identifier for this connection (an integer). Proto is the name of the protocol used for this connection. Examples The following example lists all the currently active connections initiated by this agent using the default protocol: ?- agent_connected( client, Connection, default ). <enter> Connection = 128 ; Connection = 104 ; Connection = 32 Notes See also This predicate is only available if you are using the default protocol as the primary protocol. agent event/3 agent incoming/4 Communications Agent Events

51

agUtil_trace /0
trace agent events agUtil_trace Comments This predicate works similar to agent_start/1, but also causes all the agent events to be written to a separate window. This predicate is only available if the agent utility file is loaded. Examples The following example first makes sure that the agent utility file is loaded, then creates and initializes an agent with all the default parameters. To cause the agent to stop immediately after it starts, posts an agent_stop event: ?- ensure_loaded(library('\agent\agUtil')), agent_create(ID) , agent_initialize, agent_post_event(agent_stop,_), agUtil_trace. <enter> ID = agent033290A4 Notes See also The agent must have been created, initialized and all the necessary declarations must have been made before this predicate is called. agUtil_trace/l agent start/0 agent stop/0 agUtil msg2term/3 Agent Events

52

agUtil_trace/1
trace agent events agUtil_trace(Interval) +Interval <floating point number>

Comments This predicate works similar to agent_start/1, but also causes all the agent events to be written to a separate window. This predicate is only available if the agent utility file is loaded. Examples The following example first makes sure that the agent utility file is loaded, then creates and initializes an agent with all the default parameters: ?- ensure_loaded(library('\agent\agUtil')), agent_create(ID) , agent_initialize, agUtil_trace(0.4). <enter> ID = agent033290A4 Notes See also The agent must have been created, initialized and all the necessary declarations must have been made before this predicate is called. agUtil trace/0 agent_start/0 agent stop/0 agUtil msg2term/3 Agent Events

53

agUtil_msg2term/3
convert incoming messages to Prolog terms agUtil_msg2term( Msg, Term, E ) +Msg -Term ?E <string> <term> <integer>

Comments This predicate converts an incoming message string into a Prolog term and returns the error code. Msg is the string to be converted. Term is the converted message and E is the error code that is returned. This predicate is only available if the agent utility file is loaded. Examples The following example shows an agent event handler which runs the commands sent to it by other agents. It uses agUtil_msg2term/3 to convert the incoming messages into Prolog terms: my_event_handler( incoming_msg, (MesNo, _) ) :agent_incoming(MesNo, _, Msg, _ ), agUtil_msg2Term(Msg, Goal, Err), ( Err \= 0 -> agent_post_event(urgent, error, (Err,Msg)) ; agent_post_event(new_command, Goal) ), retractall(agent_incoming(MesNo,_,_,_)). See also agUtil trace/0 Agent Events

54

Chapter 3 The KQML Library


Introduction
KQML stands for Knowledge Query and Manipulation Language and it is a language for the communication between software agents. The semantic mode underlying KQML is a simple, uniform context for agents to view each others capabilities. Each agent appears as if it manages a knowledge base. So the communication between agents are about what their knowledge base contains, requests to add or remove statements from each other's knowledge bases or requests to use knowledge in the knowledge base to pass on to the other agents. Agents communicate by sending KQML messages to each other. A KQML message is also called a performative. KQML specifications define many performatives that could be used for a variety of purposes. Using this library in conjunction with the TCP Library you can write intelligent software agents which communicate with each other working on a user specified task as a team. Using this library, you can: Build valid KQML performatives from Prolog structures, Convert KQML messages to Prolog structures, Validate KQML messages. This library confirms to the syntax specified in the following papers: Draft Specification of KQML Agent-Communication Language By The DARPA Knowledge Sharing Initiative External Interfaces Working Group, June 15, 1993. and A Proposal for a new KQML Specification, by Yannis Labrou and Tim Finin February 3, 1997 NOTE: Expressions like ((word word) (word word)) are not valid KQML expressions according to the KQML BNF. But this library will treat them as valid KQML expressions for reasons of compatibility with other agent systems and KQML implementations. 55

Representing and Converting KQML Performatives


Comments The name of a KQML performative is represented by the structure performative/1, which holds the name of the performative as a Prolog atom, (e.g. performative('stand-by') ). The KQML fields and their values are represented as a Prolog list of the form: [ ( keyword(Keyword1), value(Value1) ), ( keyword(Keyword2), value(Value2) ), .. ] The arguments of keyword/1 structures are atoms representing the KQML message field names. The arguments of value/1 structures could be atoms, strings, lists or compound terms representing the value of the field given with keyword/1. If one of those fields contains a performative itself, then the value of that field will be the representation of that performative with its own performative name, and keyword-value pairs. Examples KQML Message: (ready :reply-with 2F0B :in-reply-to g1) Prolog Representation: Performative = performative(ready) , Pairs = [ (keyword('in-reply-to'), value(g1)), (keyword('reply-with'),value('2F0B') ] KQML Message: (tell :sender B :receiver A :in-reply-to id1 :reply-with id2 :language Prolog :ontology foo :content "[bar(a,b),bar(c,d)]") Prolog Representation: Performative = performative(tell) , Pairs = [ (keyword(content),value(`[bar(a,b),bar(c,d)]`)), (keyword(ontology),value(foo)), 56

(keyword(language),value('Prolog')), (keyword('reply-with'),value(id2)), (keyword('in-reply-to'),value(id1)), (keyword(receiver),value('A')), (keyword(sender),value('B')) ] KQML Message: (standby :language KQML :ontology K10 :reply-with g1 :content (stream-about :language KIF :ontology motors :reply-with q3 :content motor1)) Prolog Representation: Performative = performative(standby) , Pairs = [ ( keyword(content), value( [ performative('stream-about'), [(keyword(content),value(motor1)), (keyword('reply-with'),value(q3)), (keyword(ontology),value(motors)), (keyword(language),value('KIF')) ] ] ) ), (keyword('reply-with'),value(g1)), (keyword(ontology),value('K10')), (keyword(language),value('KQML')) ] Notes This library tries to return the value of the keyword fields as prolog structures. KQML words are returned as prolog atoms. KQML strings are returned as prolog strings. All other KQML expressions are converted to prolog tuples or lists wherever possible.

57

The Predicates
kqml_parse_msg/3
parse a KQML message
kqml_parse_msg( String, Performative, Pairs ) +String -Performative -Pairs <string> <compound term> <list>

Comments This predicate is used for converting a string to the Prolog representation of a KQML performative. String is a string containing a valid KQML performative. Performative is the structure performative(P) , where P is an atom giving the name of the performative. Pairs is a list containing the keyword fields and values of the performative. This predicate converts KQML strings to LPA strings, KQML words to atoms and KQML expressions to prolog tuples. It will fail if the string does not contain a valid KQML performative. Examples The Prolog query to parse the KQML message: (stream-about :language KIF :ontology motors :reply-with q1 :content motor1) is shown below: ?- kqml_parse_msg( `(stream-about :language KIF :ontology motors :reply-with q1 :content motor1)`, Performative, Pairs ). <enter> Performative = performative('stream-about'), Pairs = [ (keyword(content),value(motor1)), (keyword('reply-with'),value(q1)), (keyword(ontology),value(motors)), (keyword(language),value('KIF')) 58

] The following performative contains another performative in its content field: ?- kqml_parse_msg( `(standby :language kqml :reply-with q1 :content (stream-about :ontology motors :reply-with q3 :content motor1))`, Performative, Pairs ). <enter> Performative = performative(standby) , Pairs = [(keyword(content),value([performative('streamabout'), (keyword(content),value(motor1)), (keyword('reply-with'),value(q3)), (keyword(ontology),value(motors)) ])), (keyword('reply-with'),value(q1)), (keyword(language),value(kqml))] The following performative contains an s expression in its content field which is returned as a prolog tuple: ?- Str =`(tell :content (sell plum 50))`, kqml_parse_msg(Str,Perf,Pairs). <enter> Str = `(tell :content (sell plum 50))` , Perf = performative(tell) , Pairs = [(keyword(content),value(sell(plum,'50')))] Notes A string is a valid performative if it begins with a (, and contains KQML expressions, and ends with a ). Note that there must be no whitespace between the parentheses and the characters just after or before it. For example, the string `( tell :content this-is-wrong)` will not be recognized by the parser because of the space between the opening parentheses and the performative name. If you write it like this: `(tell :content this-is-wrong)` it will become a KQML performative and will be recognized by the parser. See also kqml_make_msg/3 Representing KQML

59

kqml_make_msg/3
kqml_make_msg( Performative, Pairs, String ) +Performative +Pairs -String <compound term> <list> <string>

Comments This predicate is used for converting a Prolog representation of a KQML performative to a string. Performative is the structure performative(P), where P is an atom giving the name of the performative. Pairs is a list containing the keyword fields and values of the performative. String is a string containing a valid KQML performative. This predicate will convert the value of any field which does not contain a valid KQML expression into a KQML string (therefore converting it into a valid KQML expression) Examples The following constructs an achieve performative. Note that the content field contains a prolog tuple which is not a valid KQML expression. ?- Performative = performative(achieve), Pairs = [ (keyword(content), value(torque(motor1,5))), (keyword(ontology),value(motors)), (keyword(language),value('Prolog')), (keyword('reply-with'),value(id2)), (keyword('in-reply-to'),value(id1)), (keyword(receiver),value('B')), (keyword(sender),value('A')) ], kqml_make_msg( Performative, Pairs, KQML_Mes ). <enter> KQML_Mes = `(achieve :content "torque(motor1,5)" :ontology motors :language Prolog :reply-with id2 :in-reply-to id1 :receiver B :sender A)`

60

The following constructs a standby message which contains a stream-about performative in its content field: ?- Outer= [ (keyword(language),value('kqml')), (keyword('reply-with'),value(q1)), (keyword('content'),value(Inner)) ], Inner = [ performative('stream-about'), (keyword(ontology),value('motors')), (keyword('reply-with'),value(q3)), (keyword('content'),value(motor1)) ], kqml_make_msg( performative('standby'), Outer, KQML_Mes ). <enter> KQML_Mes = `(standby :language kqml :reply-with q1 :content (stream-about :ontology motors :reply-with q3 :content motor1))` Notes If you want to nest performatives, so that one of your keywords contain a performative as its value, then give its Prolog representation as the value of your field to construct the final performative. This is illustrated with the second example above. kqml_parse_msg/3 Representing KQML

See also

61

kqml_is_expression/1
test for a KQML expression
kqml_is_expression( Expression ) +Expression <string>

Comments This predicate succeeds if Expression is a KQML expression accepted by this library. Examples The following query succeeds: ?- kqml_is_expression( `(tell :content this-is-fine)` ). <enter> yes The following query fails, because of the spaces between the opening parentheses and the performative name, also because of the spaces after the closing parentheses: ?- kqml_is_expression( `( tell :content this-is-wrong) ` ). <enter> no All of the following are KQML expressions according to this library: (tell :content (sell plum 50)) (KQML Expression) (iota ?x (result (actionterm j action) ?x)) (FIPA S Language) (= (val (torque motor1) (simtime 5) (scalar 12 kgf))) (KIF) Notes A KQML expression can be a KQML word, a KQML comma-expression, a KQML quotation, a KQML string, a KQML performative, or an s expression like the following: (KQML_Word KQML_Expressions) (KQML_Expression) (KQML_Expression KQML_Expressions) kqml_is_performative/1 kqml_is_string/1 kqml_is_quotation/1 kqml_is_comma_expression/1 kqml_is_word/1

See also

62

kqml_is_performative/1
test for a KQML performative
kqml_is_performative( Performative ) +Performative <string>

Comments This predicate succeeds if Performative is a valid KQML performative. Examples The following query fails, because of the parentheses surrounding the value of content: ?- kqml_is_performative( `(tell :content (a_prolog_tuple(A,B)))` ). <enter> no However, if you turned the value of the content field into a KQML string, the whole message will become a valid KQML performative: ?- kqml_is_performative(`(tell :content "(a_prolog_tuple(A,B))")` ). <enter> yes Notes See also Because every KQML performative is a special KQML expression, valid performatives are also valid expressions. kqml_is_expression/1 kqml_is_string/1 kqml_is_quotation/1 kqml_is_comma_expression/1 kqml_is_word/1

63

kqml_is_string/1
test for a KQML string
kqml_is_string( String ) +String <string>

Comments This predicate succeeds if String is a valid KQML string. Examples The following query fails, because of the missing double quote: ?- kqml_is_string( ` "not a string` ). <enter> no The following is a valid KQML string which happens to contain a Prolog string: ?- kqml_is_string( `"kqml_string([``prolog string``])"` ). <enter> yes Notes The KQML specification proposal (1997) suggests that expressions in the :content that have parentheses (like Prolog facts and goals) should be enclosed in double quotes (" "). kqml_is_expression/1 kqml_is_performative/1 kqml_is_quotation/1 kqml_is_comma_expression/1 kqml_is_word/1

See also

64

kqml_is_quotation/1
test for a KQML quotation
kqml_is_quotation( Quotation ) +Quotation <string>

Comments This predicate succeeds if Quotation is a valid KQML quotation. Examples The following is a valid KQML quotation: ?- kqml_is_quotation( `'(foo)` ). <enter> yes Notes The definitions for KQML quotation and KQML comma-expression are intended to accommodate expressions in KIF that use special operators. kqml_is_expression/1 kqml_is_performative/1 kqml_is_string/1 kqml_is_comma_expression/1 kqml_is_word/1

See also

65

kqml_is_comma_expression/1
test for a KQML comma-expression
kqml_is_comma_expression( Comma_Expr ) +Comma_Expr <string>

Comments This predicate succeeds if Comma_Expr is a valid KQML commaexpression. Examples The following is a valid KQML comma-expression: ?- kqml_is_comma_expression( `(foo ,bar)` ). <enter> yes Notes The definitions for KQML quotation and KQML comma-expression are intended to accommodate expressions in KIF that use special operators. kqml_is_expression/1 kqml_is_performative/1 kqml_is_string/1 kqml_is_quotation/1 kqml_is_word/1

See also

66

kqml_is_word/1
test for a KQML word
kqml_is_word( Word ) +Word <string>

Comments This predicate succeeds if Word is a valid KQML word. Examples The following are valid KQML words: ?- kqml_is_word( `kqml-word` ). <enter> yes ?- kqml_is_word( `salt&pepper` ). <enter> yes The following query fails because the character (ASCII 128) is neither alphabetic, numeric or a special character according to the KQML syntax specification: ?- kqml_is_word( `no-word( )` ). <enter> no See also kqml_is_expression/1 kqml_is_performative/1 kqml_is_string/1 kqml_is_quotation/1 kqml_is_comma_expression/1

67

kqml_expression/2
get the Prolog representation of a KQML expression
kqml_expression( E, Prolog ) +E -Prolog <string> <compound term>

Comments This predicate returns the Prolog representation of the KQML expression given in E Examples The following are the Prolog representations of various strings containing KQML expressions: ?- Str = `(= (val (torque motor1) (sim-time 5) (scalar 12 kgf)))`, kqml_expression(Str,Prolog). <enter> Str = `(= (val (torque motor1) (sim-time 5) (scalar 12 kgf)))` , Prolog = s_expression([=, s_expression([val, s_expression([torque,motor1]), s_expression(['sim-time','5']), s_expression([scalar,'12',kgf])])]) ?- Str =`(tell :content (sell plum 50))`, kqml_expression(Str,Prolog). <enter> Str = `(tell :content (sell plum 50))` , Prolog = [ performative(tell), [(keyword(content),value(s_expression([sell,plum,'50'])))]] ?- Str =`(tell :content ``,word(sell ,plum))`, kqml_expression(Str,Prolog). <enter> Str = `(tell :content ``,word(sell ,plum))` , Prolog = [ performative(tell), [( keyword(content), value(quotation(comma(word(sell([comma(plum)]))))) ) ] ] ?- Str= `"a KQML String"`, kqml_expression(Str,Prolog). <enter> Str = `"a KQML String"` , Prolog = string([97,32,75,81,77,76,32,83,116,114,105,110,103]) See also kqml_is_expression/1 kqml_string/2 kqml_performative/2 kqml_quotation/2

68

kqml_comma_expression/2 kqml_word/2

69

kqml_performative/2
get the Prolog representation of a performative
kqml_performative( P, Prolog ) +P -Prolog <string> <compound term>

Comments This predicate returns the Prolog representation of the performative given in P. Examples The following is the Prolog representation of a performative: ?- Str =`(tell :content (sell plum 50))`, kqml_performative(Str,Prolog). <enter> Str = `(tell :content (sell plum 50))` , Prolog = [ performative(tell), [(keyword(content),value(s_expression([sell,plum,'50'])))] ] See also kqml_is_performative/1 kqml_string/2 kqml_expression/2 kqml_quotation/2 kqml_comma_expression/2 kqml_word/2

70

kqml_string/2
get the Prolog representation of a KQML string
kqml_string( S, Prolog ) +S -Prolog <string> <compound term>

Comments This predicate returns the Prolog representation of the KQML string given in S. Examples The following are the Prolog representation of two KQML strings: ?- Str= `"a KQML String"`, kqml_string(Str,Prolog). <enter> Str = `"a KQML String"` , Prolog = string([97,32,75,81,77,76,32,83,116,114,105,110,103]) ?- Str = `#6"abc\"d`, kqml_string(Str,Prolog). <enter> Str = `#6"abc\"d` , Prolog = string([97,98,99,34,100]) See also kqml_performative/2 kqml_is_string/1 kqml_expression/2 kqml_quotation/2 kqml_comma_expression/2 kqml_word/2

71

kqml_quotation/2
get the Prolog representation of a KQML quotation
kqml_quotation( Q, Prolog ) +Q -Prolog <string> <compound term>

Comments This predicate returns the Prolog representation of the KQML quotation given in Q. Examples The following is the Prolog representation of a KQML quotation: ?- Str = `'(foo bar sux)` , kqml_quotation(Str,Prolog). <enter> Str = `'(foo bar sux)` , Prolog = quotation(s_expression([foo,bar,sux])) See also kqml_performative/2 kqml_string/2 kqml_expression/2 kqml_is_quotation/1 kqml_comma_expression/2 kqml_word/2

72

kqml_comma_expression/2
get the Prolog representation of a KQML comma expression
kqml_comma_expression( C, Prolog ) +C -Prolog <string> <compound term>

Comments This predicate returns the Prolog representation of the KQML comma expression given in C. Examples The following is the Prolog representation of a KQML comma expression: ?- Str = `,word(sell ,plum)`, kqml_comma_expression(Str,Prolog). <enter> Str = `,word(sell ,plum)` , Prolog = comma(word(sell([comma(plum)]))) See also kqml_performative/2 kqml_string/2 kqml_expression/2 kqml_quotation/2 kqml_is_comma_expression/1 kqml_word/2

73

kqml_word/2
get the Prolog representation of a KQML word
kqml_word( Word, Prolog ) +Word -Prolog <string> <atom>

Comments This predicate returns the Prolog representation of the KQML word given in Word. Examples The following is the Prolog representation of a KQML word: ?- Str = `a-kqml-word`, kqml_word(Str,Prolog). <enter> Str = `a-kqml-word` , Prolog = 'a-kqml-word' Notes See also KQML words are returned as atoms and quoted where necessary. kqml_performative/2 kqml_string/2 kqml_expression/2 kqml_quotation/2 kqml_comma_expression/2 kqml_is_word/1

74

Appendix A - Argument Type Specifications


<arity>
An integer that denotes the number of arguments to a predicate. In the current system this integer is in the range [0..64]. For example given the following predicate: foo( a, b, c ). The arity of this predicate is 3, and the predicate specification is foo/3.

<buffer_identifier>
There are six types of buffer/memory file identifier; these are given in the following table: Format Description Name (Name, Index) [] Address (Address, Index) ([],integer) an atom, referring to a named memory buffer (a memory file created using fcreate/4). a conjunction of an atom, referring to a named memory buffer (a memory file created using fcreate/4) and an integer , referring to a position within the buffer relative to its start. internal buffer. an integer, referring to the address of a memory buffer. a conjunction of two integers, the first is the address of a memory buffer, the second refers to a position within the buffer relative to its start. indexed entry in internal buffer

<char_list>
A list of integers each of which is in the range [0..255]. For example the following list represents the characters 'a', 'b' and 'c'. [97,98,99] This list can also be written as: "abc" 75

Lists of this kind are also known as byte lists.

<char>
An integer in the range [0..255] that is a character code. For example, the character code for the letter 'a' is 97.

<conjunct_of Type>
A conjunction of Terms of the given type. For example the following conjunction of string is of the type <conjunct_of <string>> (`a`,`b`)

<date_time>
Time is represented as a conjunction (comma pair) of two integers, which correspond to the number of days since (1600,1,1) and a millisecond count for the current day. For example: (123,456789) means 123 days and 456.789 seconds.

<expr>
An arithmetic expression or number. For more information on arithmetic expressions and the functions allowed see is/2.

<file_name>
A file name is an atom that refers to a particular file by name and may or may not include a path and extension. For example, the following atom refers to the file FOO.PL located in the absolute directory C:\MYFOO: 'C:\MYFOO\FOO.PL' The following atom refers to the file FOO.PL located in the current directory: 'FOO.PL' The following atom may refer to the file FOO without an extension, but a default extension may be given to the file by the predicate that is using the file specification: 'FOO'

76

<file_spec>
A file specification may be either an atom or a compound_term . If the specification is an atom it refers to the file_name and may or may not include a path and extension. If the specification is a compound_term , then it should be of the form: PathAlias(FileName). Where PathAlias refers to a "logical" path_alias set up using the file_search_path/2 database and FileName is an atom that denotes a file that may or may not include a path and extension. The resultant file is found by taking the FileName relative to the directory given by the PathAlias. For example the following file specification refers to the file FOO.PL in the Prolog EXAMPLES directory: examples('FOO.PL')

<file_specs>
A list of file_specifications. For example the following list of file specifications refers to three different files: ['C:\PROLOG\FOO.PL',bar,myfiles('FRED.PL')]

<functor>
An atom that denotes the functor of a predicate. This atom cannot be the empty list []. For example given the following predicate: foo( a, b ). The functor of this predicate is foo. and the predicate specification is foo/2.

<goal>
A goal is a compound_term or an atom that represents a call to a Prolog program. For example, a goal term is: write(hello) If a variable is instantiated to a goal and occurs as a call it is known as a meta_variable , as in the following program:

77

foo( Goal ) :Goal. The following instantiates the Goal in the above example to the goal term write(hello), which is then executed: ?- foo( write(hello) ). <enter> hello

<integer_expr>
An integer or an expression which evaluates to an integer. For example, the following are all integer expressions: 1 1 + 2 10 // 1

<list_of Type>
A list consisting of terms of the given type. For example, the following list of atoms is of the type <list_of <atom>>: [a,b,c,d,e]

Meta-variables
A meta-variable is a variable which appears in place of a callable Prolog structure. LPA provides full support for the usual Edinburgh predicates =../2 and call/1, but the following methods for supporting meta-calling are far more efficient. Condition meta-variables can be bound to atoms and compound terms and called directly without using call/1. Predicate meta-variables can be used where the functor of a compound term is a variable that is bound at the time of calling the term.

<path_alias>
A path alias is an atom that refers to a "logical" path name set up using the file_search_path/2 database. It is used as the functor of a file specification to specify the location of a file. For example if the following file_search_path/2 clause has been asserted: file_search_path( myfiles, 'C:\MYFILES' ) then the following file specification refers to the file FOO.PL in the C:\MYFILES directory: myfiles('FOO.PL').

78

<pred_spec>
A predicate specification is of the form: Functor/Arity where Functor is an atom that is the functor of the predicate and Arity is an integer that specifies the arity , or number of arguments of the predicate. For example given the following predicate: foo( X ) :write( hello ). its predicate specification would be: foo/1 denoting a predicate with one argument and whose functor is foo.

<pred_specs>
A list of #pred_spec predicate specifications of the form functor / arity For example: [foo/1,foo/2,bar/4] This denotes three distinct predicates.

<window_handle>
There are four types of window handle, as shown in the following table: Name An atom that refers to a named top-level window created by Prolog. A conjunction of an atom, that refers to a named top-level window created by Prolog, and an integer that refers to the ID of a control item within the window. An integer that refers to the handle of any window (not just those created by Prolog). Handles are assigned by Windows itself and may be found using wfind/3, wlink/3 and wndhdl/2. A conjunction of an integer, that refers to the handle of any window, and another integer that refers to the ID of a child of the window.

(Name,ID)

Handle

(Handle,ID)

<number>
A number is either an integer or floating_point_number . 79

file_search_path/2
user defined fact specifying a path name file_search_path( Dirspec, Directory ) +Dirspec <path_alias> +Directory <file_spec> Within WIN-PROLOG you can use, for example, prolog(<filename>), system(<filename>) and examples(<filename>) to specify the location of a file relative to the WIN-PROLOG root directory. 'system' and 'examples' have been defined as folows: file_search_path( system, prolog('system\') ). file_search_path( examples, prolog('examples\') ). is a logical name that will be used for specifying a directory, and Directory is the path of the directory to be aliased in this way.
Dirspec

The following will define mydir in the Prolog examples directory: ?- assert( file_search_path( mydir, prolog('examples\mydir\') ) ). <enter>

Terms
Terms are the fundamental data types in Prolog. They are the building blocks from which Prolog clauses, and commands are constructed. The basic term types are: variable, integer, floating_point_number, atom , string (a unique LPA text data_type ), lists, byte_list (normally called strings in 'Edinburgh' parlance) and compound_terms .

Data Types
The following data types are used in LPA-PROLOG: atom byte_list compound_term floating_point_number integer list

80

string variable

Atom - Data Type


Atoms are text names that are used to identify data, programs, modules, files, windows, and so on. The maximum length of an atom is 1024 characters. There are four types of atoms: alphanumeric , symbolic , quoted and special_atoms .

Alphanumeric Atoms
An alphanumeric atom is one that starts with a lower-case letter (a-z) and is only followed by: alphabetic characters (A-Z,a-z), extended ASCII alphabetic characters (ASCII codes 128-154 and 160-167), digits (0,9) and underscores. The following are all alphanumeric atoms: apple a1 apple_cart longTable

Symbolic Atoms
A symbolic atom is written as a sequence of symbolic characters, and characters in the upper half of the 8-bit ASCII table. The symbolic characters are: #$&=-^~\@ `:./+*?<> The following are all symbolic atoms: & &: ++ << >> <-- .. *-/* Note that the /* appearing in the last example is not interpreted as the start of a comment.

Quoted Atoms
A quoted atom is any sequence of characters surrounded by single quotes. To insert a single quote character in a quoted atom use two adjacent single quote characters '' The tilde character (~) is used within quoted atoms as an escape character. Tilde followed by a printable character in the range '@' to '_' is used to represent a control character. For example: '~I' represents ctrl-I. The tilde character can also be followed by a three digit number representing the ASCII code of a character. This can be useful for inserting characters with an ASCII value greater than 127.

81

To insert a tilde in a quoted atom use ~~. The following are all quoted atoms: 'Apple' '123' 'hello world' '~Ibold~M~J' '~065' 'don''t care' The last example represents the atom: don't care

Special Atoms
The special atoms are as follows: ! ; [] {} end_of_file

Byte List - Data Type


A byte list (also referred to as char_lists, is a sequence of characters surrounded by the double quotes character ("). It is simply an abbreviation for the list of decimal integer ASCII codes of the characters in the sequence. For example, the byte list: "A boy" is simply a shorthand form of the list: [65,32,98,111,121] To insert a double quote character in a byte list use two adjacent double quote characters: "" As with quoted atoms the tilde character is used an escape character, allowing you to enter control characters in a byte list. For example: "~G" represents the list: [7] (To insert a tilde in a byte list use ~~.)

Compound Term - Data Type


A compound term is a structured data item that consists of a functor followed by a sequence of one or more arguments which are enclosed in brackets and separated by commas. The general form of a compound term is: functor(t1, t2, ..., tn) n 1 functor is the functor. It can be an atom or a variable name. (For further details about the use of a variable name as the functor please see the section below entitled "Meta-variables"). The term ti represents the i'th argument of the compound term.

82

The arity of a compound term is the number of arguments it has (n in the example above). We refer to functor with arity n using the notation: functor/n The following are examples of compound terms: likes(paul,prolog) % functor is likes (arity is 2) read(X) % functor is read (arity is 1) >(3,2) % functor is > (arity is 2) A compound term can be thought of as representing a record structure. The functor represents the name of the record, while the arguments represent the record fields. Note: There must be no space between the functor and the opening parenthesis of a compound term. For example: likes (paul,prolog) is not a legal compound term. Spaces between the arguments are allowed however.

Floating Point Number - Data Type


A floating point number is written as an optional minus sign (-) followed by a sequence of one or more digits followed by a decimal point (.) followed by one or more digits, optionally followed by an exponent. An exponent is written as e (or E) followed by an optional minus sign followed by one to three digits. Note that in LPA-PROLOG floating point numbers are 64-bit values in the range [2.2e308..1.7e308]. As with integers, the plus sign (+) must not be used to denote a positive floating point number. For example: 1.0 246.8091 -12.3 20.003e-10 -1.3E102 The following are not floating point numbers: .9 % does not start with a digit 3e-22 % no decimal point 34.1 e3 % contains a space before the 'e' -.7 % no digit after the minus sign 56.1e4.8 % exponent is not an integer 23. % no digit after the decimal point 83

Integer - Data Type


An integer is a number with no fractional part. It is written as a sequence of digits, optionally preceded by a minus sign (-). Note that in LPA-PROLOG integers are 32-bit values which gives them a range of [-2147483648..2147483647]. The plus sign (+) must not be used to denote a positive integer. All positive integers are written without a leading sign character. For example: 0 1 9821 -10 -64000

List - Data Type


A list is a sequence of terms of the form: [t1,t2,...,tn] n 0 The term ti is the i'th element of the list. It can be any type of Prolog term. The simplest form of list is the empty list (n = 0): [] The following example is a four element list: [[a,list,of,lists],and,numbers,[1,2,3]] Unknown elements of a list can be represented by variables. For example: [X,Y,Z] We also represent a list using the notation: [ t1, t2, ..., ti | Variable ] i 1 This list pattern represents a list that begins with the terms t1,t2,,ti with the remainder of the list (the tail) denoted by Variable. For example the list pattern: [Head|Tail] could be unified with the list: [1,2,3,4] to give the variable bindings: Head = 1 Tail = [2,3,4]

String - Data Type


84

A text data_type specific to LPA-PROLOG. This data type is capable of storing any length of text. The limit on the size of strings is set separately for input and output using the /I and /O command-line switches. Use backwards quotes to define a string: `This is a string` To insert a backwards quote character in a string use two adjacent backwards quote characters: `I don``t care`

Variable - Data Type


A variable name is an alphanumeric sequence of characters beginning with an upper case letter (A-Z) or an underscore ('_'). The alphanumeric sequence can include '_' and characters from the upper half of the ASCII table. For example, the following are variable names: Anything _var _1 X Var1 Quoting with single quotes overrides the variable name convention. For example the following are both quoted atoms: 'Anything' '_var' An underscore on its own is an anonymous variable.

85

Appendix B - Overview of KQML Agent Examples


By Charles Langley 2002 with acknowledgements to Dr T Hirst, Open University The directory examples\agents\kqml contains an example which shows how agents can communicate with each other via the Knowledge Query Manipulation Language (KQML). Files included in this directory which are needed for this example are: FAC.PL This is the facilitator agent which enables other agents called "clients" to communicate with each other. The facilitator is like a smart telephone exchange routing messages from client agents to other client agents. The agent architecture used here is that of a facilitator with multiple clients. The facilitator's role is a little like that of a telephone exchange the Facilitator exists in order to route messages from client agents to other client agents, and also to

Cl

Client1 asks

Cl

Message from Client3 forwarded to

F ilit t

Client2 asks Facilitator to send list of registered client agents

Client3 asks Facilitato Cl

Reply from Client1

provide information to clients as to which other agents are registered with it. The various agents need to be run, each on its own Win-Prolog session (process) either on the same computer or different computers over the internet. To see this in action, the first thing to do is to load in the program for the facilitator agent. Using the Open.. option on the WIN-PROLOG File menu, select 86

the file FAC.PL. Having loaded the file, use the Compile option on WIN-PROLOG's Run menu.

Next, issue the following command in the Prolog Console window: ?- fac(facilitator,2000). <enter> Two new windows should now have opened, one called FACILITATOR and the other Agent Trace. The first new window displays the status of the facilitator agent. You will be monitoring the behaviour of the facilitator using these windows, rather than the Console, so you can minimize the main WIN-PROLOG window onto the Windows task bar (but don't close the window) to keep your screen tidy. If you look at the facilitator window, it will give you some technical details about the facilitator. These include its name (facilitator), its host (an identifier for the machine you are using, e.g. localhost for a standalone machine or oemcomputer, or else an internet address such as www.somehost.com) and the port on which it is listening (2000). If an application wants to have a presence on a network, then it opens a port and listens for messages on it. Other applications can then communicate with the first application by opening a connection to this port. Note that many external applications can connect to the same port at the same time. To connect to a port, an application must first identify the host on which the port has been opened, and the port number. You can also look at the performatives supported by the facilitator (click on the Performatives button in the facilitator window). These are the basic building blocks of the KQML language. You can also look at the agents currently registered with the facilitator (Registered), and the performatives advertised by registered agents (Advertised). For each agent to be autonomous, it must have its own thread of control. This is achieved by running each agent in its own Prolog process (that is, its own Prolog environment).

87

Start another WIN-PROLOG process now You should do this in the same way you started WIN-PROLOG for the facilitator. Once again, double click on the WIN-PROLOG icon, then using the File/Open option, select the file CLIENT.PL; this file contains the specific agent program and automatically loads in the generic agent toolkit. Once the file is loaded, compile it using the Run/Compile option and issue the command in the console window: ? client. <enter> This initial Client agent, called MyAgent, is a simple agent that knows a few facts about peoples' ages. The agent window allows you to control the behaviour of your agent. Once again, you may minimize the main WIN-PROLOG window (but

don't close it). The agent window displays the name of the agent and several controls for it, a panel in which you can create the content of KQML messages, and a panel that displays a log of messages received and transmitted by the agent.

88

In the panel called The Facilitator are some details you should fill in about the facilitator you are going to use. In this case, set its name to facilitator, its host to the same host as the facilitator you have launched already. Finally, set the port number to 2000 Start the agent running by clicking on the Start button in the agent window. This simply gets the agent code itself running. The next thing to do is open a link from the agent to the facilitator. Click on the Open Channel button. You should get an OK message in the agent window. Having opened a link to the facilitator, the agent must now register with it. Click on the Register button in the agent window. In the bottom, you should see a log of the performative you have just sent. You now should see that the agent has received a message from the facilitator asking the agent to identify itself. Click on the Whoiam button to give the facilitator some detailed network information about the agent. Start a third WIN-PROLOG process now In the same way as you did before, launch another WIN-PROLOG process; and open the file Client.pl again. This launches a second agent who also knows something about peoples' ages. As before, you may now minimize, but not close, the main WIN-PROLOG window to the Windows task bar. Give the agent the same facilitator details as before. Start this agent, connect to and register with the facilitator and send it the whoiam performative. Get a list of agents connected to the facilitator by clicking on the ListAgents button. This second client must have a name distinct from the first. Let us suppose that we call it simon. After changing the client's name to simon, make sure that the details in the panel called The Facilitator are correct and use the Start, Open Channel, Register and WhoIam buttons again.

Forwarding messages
You have now set up a system in which two agents are connected to the same facilitator, and may communicate by forwarding messages to each other via this facilitator. In agent simon's message panel, set the performative to ask-one, the receiver to MyAgent and the message content to "how_old_is(tom, X ).". Forward this message to MyAgent via the facilitator by pressing the Forward this Performative button. MyAgent will receive the query and reply with the first answer it finds in its own database that satisfies the relation how_old_is(tom, X). If MyAgent knew the ages of more than one person called tom, simon could request the ages of them all using the performative ask-all. 89

Now make simon ask MyAgent about the age of phil. It will get back a reply similar to this: false(how_old_is(phil,_32)). This is because sam doesn't know anything about the age of phil. The item _32 is an internal variable that has not been assigned a value which is generated by the program you will probably see a different variable name. Agents can add a fact to another agent's database using the add-one performative. Get simon to send the add-one performative to MyAgent with message content age(phil, 33). You can inspect the actual performative that is generated when you click on the Forward this Performative button because it will appear in the outgoing message in the message window. It should look something like this:

(forward :content (add-one :receiver MyAgent :reply-with answer :in-reply-to nil :language prolog

Next forward to MyAgent the ask-one performative again, asking how old phil is. The Client Agents also know another two relations, younger_than(X,Y), which identifies whether person X is younger than person Y. and older_than(X,Y). Try getting MyAgent to use the ask-one performative to ask simon whether tom is younger than mary. How would you get MyAgent to ask simon for the names of all the people younger than tom? (Remember, both simon and MyAgent can handle the ask-one and ask-all performatives). Try doing this now.

Broadcasting messages
It is also possible to ask the facilitator to broadcast a message to all other agents that are registered with it. To show this, we need yet another client agent. Start a fourth WIN-PROLOG process now Call the new client zoe, and set zoe's name, host and port as before. 90

Next switch back to the MyAgent client. Note that in order to issue a broadcast request to the facilitator we need to set the Receiver field to the same name as the sending agent (in this case MyAgent).

Technical Appendix
By Z. Meltem ISMIK 1999

CONVERSATION POLICY
The communication between the facilitator and the client agents takes place through the connection originally opened by the client agent. The client agent must be using the same low level protocol as the facilitator agent. You can find out this protocol by displaying the details of the facilitator and the client agents. (It will normally be the default protocol. If you want to change this, see agent library documentation). All messages sent to this facilitator must be in KQML. All language, ontology, reply-with and in-reply-to fields are optional. This facilitator will ignore any fields that are not required. Client agents are expected to behave similarly (ignoring the kqml fields which are not required rather than sending error messages).

PERFORMATIVES
Performatives That Can Be Sent To This Facilitator: register 91

unregister reconnect disconnect contact-information whoiam list-users request-address forward Performatives Sent by This Facilitator: error sorry identify-self address whoiam reply Although this facilitator will send error, sorry and reply performatives, it is not equipped to handle these performatives coming from client agents. However, 'identify-self' and 'whoaim' will work both ways. At present, broadcast, advertise, recommend-one and recommend-all performatives are not fully implemented. If you would like this facilitator to be able to handle more performatives see MODIFYING THE FACILITATOR CODE below. FAGENT = The name of the facilitator agent

SENDERAGENT = The sender of the performative OTHERAGENT = The receiver of the performative AGENTNAME = The name of an agent

ERROR

92

Facilitator sends the following message if the incoming message cannot be parsed: (error :sender FAGENT :content syntax-error)

SORRY
This performative is sent if the facilitator can parse the message but something else is wrong: (sorry :sender FAGENT :receiver AGENTNAME :content ERRMESSAGE) ERRMESSAGE can be: 'already-registered' (reply to a register request) 'receiver-disconnected' (reply to a forward request) 'not-understood' (the facilitator cannot process this performative) 'ill-formed-message' (the message is syntactically correct, but doesn't make sense. i.e an agent advertising a performative using the name of another agent etc.) `no-suitable-agents` (in reply to a recommend-one, recommend-all, broker-one, broker-all etc. ) or one of the kqml expressions below: (expected Perf1 Perf2 Perf3 .. ) (missing Field1 Field2 .. ) which means the facilitator was expecting one of the specified performatives or a required field is missing from the message. Example: If the facilitator receives a message from an unregistered agent the reply will be: (sorry :sender facilitator :receiver agent1 :in-reply-to ref1 :content (expected register)) If a message doesn't have a sender: (sorry :sender facilitator :in-reply-to ref2 :content (missing sender))

93

REGISTER
SENDERAGENT wants to register with the facilitator FAGENT. Content is optional, if it is not WHOIAM, or CONTACT-INFORMATION then the FAGENT may ask for it by sending an IDENTIFY-SELF performative. (register :sender SENDERAGENT :receiver FAGENT :password PASSWORD :content WHOIAM or CONTACT-INFORMATION :reply-with RW ) The facilitator replies with: (register-accepted :sender facilitator :receiver AGENT :in-reply-to RW) If the facilitator does not have the contact information or description of this agent, then this is followed by an IDENTIFY-SELF.

IDENTIFY-SELF
SENDERAGENT wants the OTHERAGENT to introduce itself. The receiver will reply with a WHOIAM or CONTACT-INFORMATION performative. TRANSPORT-ADDRESS performative is also OK, if the content field contains a CONTACT-INFORMATION performative. (identify-self :sender SENDERAGENT :receiver OTHERAGENT :reply-with RW :in-reply-to Reference)

WHOIAM
SENDERAGENT introduces itself to FAGENT. :description is optional and can include/exclude any field as required. The description fields shown below lists the languages, protocols, performatives understood by this agent and its type. Acceptable reply to an identify performative. Can be sent any time. This performative replaces the previous description and contact information (if any). (whoiam :sender SENDERAGENT :receiver FAGENT 94

:password PASSWORD :in-reply-to Reference :content (contact-information :protocol Proto :host Host :port Port :address Addr) :description (description :languages (languages L1 L2 etc) :protocols (protocols P1 P2 etc) :performatives (performatives P1 P2) :name SENDERAGENT :type AGENTTYPE))

DISCONNECT
SENDERAGENT wants to disconnect from the facilitator FAGENT. (disconnect :sender SENDERAGENT :receiver FAGENT :password PASSWORD)

RECONNECT
A previously registered agent,SENDERAGENT, wants to reconnect to the facilitator FAGENT. (reconnect :sender SENDERAGENT :receiver FAGENT :password PASSWORD) The facilitator will reply with a CONNECTION-ACCEPTED performative.

CONNECTION-ACCEPTED
The reply to a RECONNECT performative. (connection-accepted :sender FAGENT :receiver SENDERAGENT).

LIST-USERS
SENDERAGENT wants to receive the list of agents who are registered with the facilitator FAGENT. (list-users :sender SENDERAGENT :receiver FAGENT :password PASSWORD :language LANGUAGE) If the LANGUAGE is kqml, then the faciliator will send a valid KQML expression, otherwise it will send a prolog list converted to an s expression (the language field of the reply will be set to 'sprolog' ). 95

REGISTERED-AGENT
SENDERAGENT (facilitator) is sending a list of currently registered agents to OTHERAGENT. (registered-agent :sender SENDERAGENT :receiver OTHERAGENT :language sprolog :content LIST) If this performative does not contain a language field the content will be a valid kqml expression of the following form: (registered (agentname1 status1) (agentname2 status2)..) If the language is sprolog then the content will look like: ((agentname1 status1) (agentname2 status2)..) EXAMPLE = (registered-agent :sender facilitator :receiver simon :language sprolog :content ((simon connected)(sally disconnected)) (registered-agent :sender facilitator :receiver simon :language kqml :content (registered (simon connected)(sally disconnected))

REQUEST-ADDRESS
SENDERAGENT wants the faciliator FAGENT to send the address of the agent given in content. (request-address :sender SENDERAGENT :receiver FAGENT :content AGENTNAME) The reply will be an ADDRESS performative.

ADDRESS
Reply from the facilitator to a REQUEST-ADDRESS performative (address :sender FAGENT :receiver SENDERAGENT :name AGENTNAME :host HOSTNAME or null :port PORTNUMBER or -1 :description DESCRIPTION or null) 96

FORWARD
Request from a registered agent to forward the performative given in content to the agent specified with the :to parameter ( :reply-with is optional, :in-reply-to is ignored ) (forward :from FROMAGENT :to TOAGENT :sender FROMAGENT :receiver FAGENT :content (PERFORMATIVE-TO-BE-FORWARDED)) The Following Constraints Hold: FROMAGENT must have been registered. TOAGENT must have been registered (or it can be FAGENT). The facilitator will reply with a standard reply performative if the message is successfully sent (but this does not guarantee that the TOAGENT has successfully received the message).

REPLY
Reply from the SENDERAGENT to OTHERAGENT, usually reporting the result of an earlier request made to the SENDERAGENT. (reply :sender SENDERAGENT :receiver OTHERAGENT :in-reply-to REFERENCE :content RESULT) The RESULT will be a performative if it is a reply from the facilitator to a recommend request. Example: Facilitator will send the following to the agent called 'myagent' to report that the forward message sent earlier has been received, understood and processed: (reply :sender facilitator :receiver myagent :in-reply-to forwardresult :content done) This reply doesn't guarantee that the other agents involved (for example in the case of a forward or broadcast request), has received or processed the message.

MODIFYING THE FACILITATOR CODE

97

The facilitator converts the incoming messsages into events by using the predicates defined in the file 'kqmlutil.pl' and then handles them by a handler previously defined and declared by agent_declare/2. Example: The performative 'register' A client agent who wants to obtain the list of agents that are registered with this facilitator sends the following KQML message: (register :reply-with regresult :receiver facilitator :sender client) When this message is received, the predicate kqml_parse_msg/3 converts it into to a Prolog list and a 'list-users' event is posted by the predicate kqmlUtil_perf2event/3. This event is then handled by the handler fac_kqml/2 which adds the agent called 'client' to the faciltator's database and replies with the following performative: (register-accepted :in-reply-to regresult :receiver client :sender facilitator) If you want this facilitator to respond to more performatives: 1. Write an additional clause for kqmlUtil_perf2event/3 giving the name of the performative as the first parameter. This clause should extract the values you need from the KQML message (the Prolog list Pairs) by using the predicate kqmlUtil_value/3 and post these values in addition to the extra parameters with the event generated. The extra parameter for this facilitator is always the communication channel where this message has come from. This is used for replying to the message. Example: kqmlUtil_perf2event('tell', Pairs, ExtraParams) :kqmlUtil_value( sender, Pairs, Sender ), kqmlUtil_value( 'reply-with', Pairs, RWith ), kqmlUtil_value( content, Pairs, Content ), agent_post_event( tell, (Sender,RWith,Content,ExtraParams) ). When a 'tell' performative is received the code above will generate a 'tell' event, similar to the one shown below: agent_event(3,tell,(client,replywith,`hello`,116)) 2. Write the code that will handle this performative as an additional clause for fac_kqml/2. Example: For the 'tell' performative in the above example:

98

fac_kqml( 'tell', (Sender,RWith,Content,Channel) ) :% do what you want here... % you can use the extra parameter Channel to send a reply. - Declare this event at the beginning of the facilitator code by adding it to the facilitator event handlers list (coded in fac_handlers/1). - Recompile and start your facilitator. Examine the facilitator and the client agent code for handling events that are generated by the user or the agent library.

99

Appendix C Overview of Stocky Example


Introduction
This appendix documents the Stocky example in the EXAMPLES\AGENTS\STOCKY folder. A loader utility (LOADER.PL) is provided for this example.

Intelligent trading agents


Over the next few exercises, you will construct a multiagent system that models share dealing in a fictional stock market. We start by giving you the context: how share dealing can be simulated, what terms like market maker mean, and so on. Then we show how to construct the MAS, then we finish with the design and implementation of an intelligent trading agent. Although you need to spend some time reading about the context, this set of exercises will demonstrate how a recognizable model of a complex system can be constructed using a multiagent system built from a small number of reusable agents. Acknowledgements are due to the United Kingdom's Open University with which we wrote an earlier version of this document for use in their course 'T396 Artificial Intelligence for Technology'. Please note that Agents constructed with LPA's Agent Toolkit are designed to run on separate Prolog processes (one per agent), and communicate with each other using TCP/IP protocols. Support is also provided for the use of the standard agent communication language KQML.

Quote-driven trading
The setting for the exercise is a model of a quote-driven trading environment (Figure 1)

100

Figure 1: Four market makers dealing with the bourse There are two sorts of entity in our model. Market makers (MARK, MM01, MM02, MM03 in the figure) Market makers are the dealers. Each market maker is authorized to buy or sell a stock a quantity of shares in a company. A market maker holds stocks in his or her book. For the stocks in the book, the market maker is obliged to maintain both a bid price (what they will pay) and an ask price (what they will sell for). Market makers also advertise a volume, the number of shares (in thousands) they are willing to buy or sell in any given transaction. Bourse (STOCKY in the figure) we've given this entity the term used in continental Europe for a stock market. The bourse maintains a central database of all market makers' quotes. When the stock market receives an order to buy or sell it consults this database to find the best price quoted for the stock concerned. The order is then forwarded to the market maker making that quote. This market maker is obliged to accept the order, because all quotes are binding. We have provided you with programs that implement a facilitator agent that is capable of performing all the actions required of the bourse. In addition, we have specified a generic market maker agent which is customisable. You can use these programs to create many instances of a market maker agent, one per Prolog process, and each with its own name. The generic market maker agents are provided with a set of trading rules (knowbot.ksl, which you can inspect), which allow them to trade intelligently. You will have an opportunity to write your own trading rules for the customisable market maker agent.

Stock market facilitator


101

The stock market facilitator agent maintains a list of prices quoted by the market makers registered with it. When a buy or sell order is received, the stock market agent executes this request with the agent offering the best price for the appropriate stock. Start a Prolog process and load in the file EXAMPLES\AGENTS\STOCKY\STOCKY8.PL. To start the facilitator agent, type: ?- stocky(2000). <enter> The Stockmarket Facilitator window is not too informative at this stage it simply reports configuration information for the facilitator. Rather than clutter your desktop with unnecessary windows, you can minimize the main WIN-PROLOG window onto the Windows task bar, but don't close it. Please note that LOADER.PL launches the WIN-PROLOG session which will run Stocky with additional memory allocated.

Market maker agents


The market maker agents are all implemented using the same underlying agent program, although each agent must run in its own process. Start a new Prolog process, and load in the generic market maker agent program EXAMPLES\AGENTS\STOCKY\TRADER.PL. Next type: ?- mm0n. <enter> This will launch the agent control panel (figure 2).

102

Figure 2 Market maker control panel Minimize the main WIN-PROLOG window to keep your screen tidy. The top of the market maker window reports information about the name of the facilitator's host machine, the port to which the facilitator is connected, and the facilitator's name. There is also a text box labelled Me for you to enter the name of the market maker agent itself. This must be exactly four alphanumeric characters long. Each agent you create should have a different name and be run in its own flexAgent process. Enter a name for your agent now, e.g. bill, jim7, jakk, mary. You have to start the market maker agents before they can connect to the facilitator. Start your agent now. The connection, registration and identification process with the facilitator uses the Connect, Register, Whoiam and ListAgents buttons in that order. Connect your first market maker agent to the stock market facilitator, and then send the Register and whoIam performatives. As well as network-related information, the interface for each market maker agent also contains various sorts of information about the agent's position and the current state of the market. Quote information for a particular stock is provided by the stock market under the heading Competing quotes. This shows the quotes for a given stock offered by all registered market makers who trade in that stock. The user can change which stock is displayed by typing the stock name into the Stock field and pressing the 103

Get Quote button. As well as showing a list of quotes for the selected stock, the Competing Quotes frame also shows the best bid price and best ask price for the stock displayed. If an agent wants to buy or sell a stock, it will do so at the best price. That is, an agent can only buy a particular stock from an agent offering the lowest unit price, and sell a stock to an agent offering the highest unit price. The second panel containing quote information is the Workstation panel. This displays all the stocks in the market maker's book, with the market maker's own quotes for each stock. It also shows the market maker's position, which is the number of stocks currently held. This number can be negative if the market maker has sold more stocks than were owned at the start. To change the prices quoted by a particular agent, enter new values in the Bid and Ask boxes, then click on the Quote button to issue this quote to the market. The quote includes the volume your agent is prepared to trade. Agents can only buy or sell stocks in volumes for which a quote exists. At the bottom of the window is a status bar that displays incoming market information, a window displaying the agent's current profit/loss, and two mode buttons that put the agent into either user or knowbot mode. In user mode, a user can buy and sell shares via the agent. In knowbot mode, the agent can trade autonomously, using the market information and its current position to inform its buy and sell trades. Once you have registered your market maker agent, you should announce your quotes for each stock. Enter the name of the stock in the stock window (ici, shel, bp, or glxo) and your bid and sell prices. You are advised that at the previous close of market, you were advertising the prices in Table 1. Table 1 Opening prices for stocks traded
Stock ici bp shel glxo Bid 631 545 682 427 Ask 633 548 687 431

Initially, each agent has a zero position in each stock. The volume is the number of shares (in thousands) you contract to buy and sell at the quoted price (2 is a good number to start with). You may make your quote known to the bourse and any other connected market maker agents by pressing the Quote button. Start two new Prolog processes, load in the TRADER.PL file and start a market maker agent running in each (remember to give them different names). Let these agents quote slightly different prices to the first agent. For example, the first agent (mm01) may have the default quote values for ici, the second (mm02) may quote one lower than those values and the third agent (mm03) may quote one higher than them. In this case, if mm01 puts in a buy order (by pressing the Buy button on mm01's control panel) it should buy stock from mm02, which is

104

quoting the lowest ask price. If mm01 now puts in a sell order, it should sell the shares to mm03, which has the highest bid price. Recall, you can obtain the latest prices for an agent by clicking the Get Quote button; and the agent can announce a new price for a stock in its book if you click on the Quote button.

Exercise 1.
Using three agents connected to the stock market facilitator and quoting different prices to each other, try buying and selling stocks between each of the agents. Recall, when an agent issues a buy order, it will buy from the agent quoting the lowest bid price. When an agent issues a sell order, it will sell to the agent offering the highest ask price. Try changing the prices your agents quote to the rest of the market and see if you can identify any sensible rules for adjusting their value.

Trading sessions
Real stock markets use the idea of a trading session to simplify their accounting procedures. A trading session is a fixed period, for example, one month. Ideally, market makers start and end a trading session with a zero position in each stock they try not to hold any stocks to begin with, or to finish with. During the trading session, market makers buy and sell stocks, continuously adjusting their quotes according to market news and the stocks they currently hold their position. They will also buy or sell stocks if they can make a profit compared with the price at which they last sold or bought them. By the end of the session, they will try to have a zero position and an overall profit. Rather than use a fixed period, our stock market model operates over a period defined by another agent we've called market news. This agent simulates a larger, outside market by issuing buy and sell orders to the market maker agents. The market news agent will also request the bourse to broadcast market news as the company Reuters does to the market makers. This news may be used by the market maker agents to help them fix their quotes and deliberate on their position. The market news agent is also used to close a trading session by sending a market-closed message at the end of the script it uses to generate trades and market news. Start a new Prolog process for the market news agent, and load in the file SCRIPTY8.PL. Raise the control panel with the command: ?- scripty. <enter> Start the agent, connect it to the bourse and register it in the normal way. Now press the Execute Script button to start the news ticker. You should see that any

105

market maker agents connected to the bourse start to receive market news, which may be exploited by the market maker.

Knowbot market makers


The market maker agents come with an example set of flex rules for running in the knowbot mode. In this context, a knowbot is an intelligent software robot that performs the role of a market maker. Open the file KNOWBOT.KSL into a text editor so that you can see how the rules are written.You will notice that the rules are written in an object-oriented way using frames. The frame definitions can be found in the file KNOWBOT.KSL. You can look at the contents of this file but you should not change them. There are three types of frame: stock, quote, and position. Their descriptions follow with the default fields shown in italics. Stock - An instance of a stock is labelled with the name of the stock ici, shel, bp or glxo. Each instance contains news about the stock (good or bad); the bid and ask price for that stock, as reported via the stock market; and the market maker's last_paid_price and last_sold_price, the prices at which the agent last bought or sold the stock respectively. Quote - This frame contains fields for the market maker making the bid, the stock being traded, the bid and ask prices and the volume. There are three instances of this frame: myquote, bestask and bestbid. Position - This frame contains information about the agent's current position, specifically the name and number held of the stock under consideration. Which stock this is at any one time is determined elsewhere in the agent program.

Exercise 2
With several market maker agents connected to the bourse, set all but one market maker agent into the Knowbot mode by clicking on the Knowbot button. Issue buy and sell orders from the user-controlled market maker, as well as changing its quoted prices. Do the autonomous market makers behave as you would expect them to? You can look at the rules each agent fires by raising the appropriate Console window. Now try running the market with the market news agent connected as well, and executing its script. How well do the autonomous agents perform? From your inspection of the knowbot.ksl rules, you may have noticed that there are several things that an intelligent agent may do change the bid price of a stock, change the ask price of a stock, buy or sell a particular stock.

106

If you would like to modify the rules a market maker uses, you may do so by making a copy of KNOWBOT.KSL, and changing the contents of the original file. Start a WIN-PROLOG process, and issue the command: ?- ensure_loaded(system(flexenv)). <enter> Next, open, edit and compile KNOWBOT.KSL, save it, load in the TRADER.PL file, then enter the 'mm0n.' command. This agent will now apply your expert rules.

107

Index
agent_assert/1 agent_assert/2 agent_asserta/1 agent_connected/3 agent_create/1 agent_create/2 agent_declare/2 agent_declare/4 agent_declare/5 agent_event/3 agent_id/4 agent_id_det/9 agent_incoming/4 agent_initialize/0 agent_load/1 agent_monitored/1 agent_post_event/2 agent_post_event/3 agent_replace/2 agent_reset/0 agent_retract/1 agent_retractall/1 agent_save/0 agent_save/1 31 32 33 51 13 14 22 29 25 45 46 47 49 20 19 44 41 42 36 12 34 35 15 16 agent_save/2 agent_start/0 agent_start/1 agent_stop/0 agent_undeclare/2 agent_undeclare/5 agUtil_msg2term/3 agUtil_trace /0 agUtil_trace/1 kqml_comma_expression/2 kqml_expression/2 kqml_is_comma_expression/1 kqml_is_expression/1 kqml_is_performative/1 kqml_is_quotation/1 kqml_is_string/1 kqml_is_word/1 kqml_make_msg/3 kqml_parse_msg/3 kqml_performative/2 kqml_quotation/2 kqml_string/2 kqml_word/2 17 38 39 40 24 27 54 52 53 73 68 66 62 63 65 64 67 60 58 70 72 71 74

108

You might also like