Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

imit_model / AnyLogic / UsersManual(AnyLogic)

.pdf
Скачиваний:
125
Добавлен:
06.06.2015
Размер:
4.28 Mб
Скачать

AnyLogic V User’s Manual

postOffice

PostOffice

recipient1

 

 

Class: Recipient

 

Startup code:

recipient2

input.registerAddress();

 

recipient3

Recipient

 

Name: output

On receive action:

if( msg instanceof RegMsg ){ RegMsg rm = (RegMsg)msg; addresses.add( rm.source );

}

Additional class code:

Vector addresses = new Vector(); void sendTo(InfoMsg msg, Port destination){

msg.address = destination; send(msg);

}

Name: input

On receive action:

if (msg.address == this || msg.address == null ) {

return true;

}

else {

return false;

}

Additional class code: void registerAddress() {

RegMsg msg = new RegMsg (); msg.source = this;

send( msg );

}

Figure 89. Sending messages to specified addresses

You have implemented message sending to the specific recipients in your system: sent messages are accepted only by the recipients with the specified destination addresses.

7.4.7.1 Sending a message to a specific group of recipients

Now you need to implement periodical delivery to the specified groups of subscribers. You need to keep subscriber addresses lists at the post office and deliver periodicals only to members of these lists. The post office announces new periodical and a recipient subscribes on it by sending a confirmation message on announce reception.

Define the SubscrMsg message class to represent periodical announces. The periodName member variable carries the periodical name. The address member variable is used to carry the subscriber destination address in the confirmation message.

Type

Name

Default

Port address

© 1992-2004 XJ Technologies http://www.xjtek.com

187

Chapter 7. Message passing

String periodName

Define the PeriodicalMsg message class to represent periodicals. The addresses member variable is used to carry the subscriber addresses list. The periodical member variable represents the periodical itself.

Type

Name

Default

 

 

 

Mail

periodical

 

 

 

 

Vector

addresses

 

Type the following code in the Additional class code property of the output port.

String timesName = new String(“Times”);

String USATodayName = new String(“USA Today”);

Vector timesSubscribers = new Vector();

Vector USATodaySubscribers = new Vector();

void announcePeriodical( String periodicalName ){ SubscrMsg msg = new SubscrMsg(); msg.periodName = periodicalName;

send(msg);

}

The times and USAToday member variables keep information about “Times” and “USA Today” subscribers. The timesName and USATodayName member variables define periodical names. The announcePeriodical() method announces a subscription on a periodical. The periodical name is specified as the method parameter.

Substitute the code in the On receive action properties of input ports with the following code:

if ((msg instanceof MailMsg)&&((msg.address==this)||(msg.address==null) )){ //process a mail addressed to this recipient or to all recipients

return true;

}

else if ( msg instanceof SubscrMsg ) {

188

© 1992-2004 XJ Technologies http://www.xjtek.com

AnyLogic V User’s Manual

if (subscribe){ msg.address = this;

send(msg); // subscribes to the periodical if subscribe is true

}

return true;

}

else {

PeriodicalMsg message = (PeriodicalMsg)msg; if message.addresses.contains(this){

// process periodical sent to this subscriber return true;

}

}

As shown above, if the recipient wants to subscribe to the announced periodical (it is defined by its subscribe member variable of boolean type), it returns the message to the post office in response to announce.

Substitute the code in the On receive action property of the output port with the following code:

if( msg instanceof RegMsg ){ RegMsg rm = (RegMsg)msg;

addresses.addElement( rm.source ); //add unknown address

}

else {

SubscrMsg sm = (SubscrMsg)msg;

if (sm.periodName.equals(timesName)) timesSubscribers.addElement(sm.address);

else if (sm.periodName.equals(USATodayName)) USATodaySubscribers.addElement(sm.address);

}

© 1992-2004 XJ Technologies http://www.xjtek.com

189

Chapter 7. Message passing

Now the subscription messages are processed at the output port. The subscriber addresses are added to the corresponding address lists.

Specify the sendtoSubscribers() method in the Additional class code property of the output port.

void sendToSubscribers( Vector subscribers, PeriodicalMsg periodical ){

msg.addresses = subscribers;

port.send(msg);

}

Call this method to send periodicals to the specified group of subscribers, providing the subscriber address list and the message as method parameters. For instance, to deliver new “USA Today” issue to the subscribers, you should write:

PeriodicalMsg issue = new PeriodicalMsg();

sendToSubscribers( USATodaySubscribers, issue );

7.4.7.2Receiving a message only from a specific object or a group of objects

According to the message routing rules, ports accept every incoming message. However, it is frequently needed to receive a message only from a certain object or a group of objects, rather than from all of them.

Figure 90. Default message reception

190

© 1992-2004 XJ Technologies http://www.xjtek.com

AnyLogic V User’s Manual

This task is bisymmetrical to the task described in section 7.4.7, “Sending a message to a specific recipient / a group of recipients”. Thus the implementation concept is the same: you need to define unique port identifiers to mark outgoing messages and filter messages at a recipient port by sender identifiers. Therefore, you need to define the message class with a custom field to carry the sender identifier and specify the list of authorized senders at the recipient object.

Name: objectA

Parameters:

String ID “first”

Name: objectB

Parameters:

String ID “second”

Name: objectC

Parameters:

String ID “third”

objectA

objectB

objectC

recipient

Class: Recipient

 

 

Recipient

Startup code: senders.addElement(“first”); senders.addElement(“third”);

Additional class code:

Vector senders = new Vector();

Figure 91. Making up authorized senders list

Again, as described in section 7.4.7, “Sending a message to a specific recipient / a group of recipients” you can build this list manually at the model design time as shown in Figure 91 or programmatically at runtime by implementing object registration mechanism described in section 7.4.5, “Getting information on connected objects” at the recipient object. Figure 92 shows one of possible implementations.

© 1992-2004 XJ Technologies http://www.xjtek.com

191

Chapter 7. Message passing

objectA

objectB

objectC

Class: Message

Parameters: source “first”

recipient

a)

objectA

objectB

objectC

Figure 92. Message filtering

recipient

Class: Message

Parameters: source “second”

b)

7.4.8Verifying port connections at runtime

Sometimes you may need to verify port connections in your model. Port connection verifying is commonly used when your model has several port types and it’s essential to allow message passing only between ports of certain types. When editing your model you can establish connection with a port of forbidden type that causes a logic error. Therefore, you need to detect an invalid connection at runtime by implementing your own checking mechanisms. You can define specific actions to be performed on invalid connection detection, the most obvious is showing an error message using runtime error ability.

Suppose you need to detect invalid port connections in the simple manufacturing model. In this model a raw material supplier supplies product processing machines with raw material. After processing at a processing machine, a resulting product is delivered for the storage to a warehouse.

The model structure is shown in Figure 93. Raw material supplier is represented by supplier object, machine - by machine object, warehouse - by warehouse object.

supplier

 

machIn

 

machine

 

 

warIn

 

warehouse

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

prodOut

 

 

 

 

 

machOut

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Figure 93. Simple manufacturing model

192

© 1992-2004 XJ Technologies http://www.xjtek.com

AnyLogic V User’s Manual

Constructing the model from a great number of objects, you may establish invalid connections. Suppose you have made a mistake when editing your model – e.g., you have connected two output ports in error. In this case you can hardly detect the error: no error message will be displayed while your model will work incorrectly.

supplier1

supplier2

supplier3

machine1

machine2

machine3

warehouse1

Figure 94. Invalid port connection in the manufacturing model

If you have well-defined input and output ports in your model, you can detect invalid connection of two output ports by message arrival to an output port. Type the following code in the On receive action property of the output port to terminate the model simulation and show the error message on message reception at the port:

Engine.error("Error: The output " + this.getFullName() + " port has invalid

connection. "); //terminates simulation

Generally, you should implement a more sophisticated mechanism to check proper material flow in this model. According to the model logic, an entity sent by a supplier should be sent to a machine first and then to a warehouse. Thus, only the prodOut ports can be connected with the machIn ports and the machOut ports can be connected only with the warIn ports.

You can define a dedicated message class for each port class. Then each port class will send only the messages of the specific type and you can verify port connections by checking incoming message types.

In our model each entity is represented by its own message class: raw material is represented by a message of the Material type and a product – by a message of the Product type. The

© 1992-2004 XJ Technologies http://www.xjtek.com

193

Chapter 7. Message passing

messages of the Material type should be received only at the machIn ports. Similarly, the messages of the Product type should be received only at the warIn port.

The checking procedure is specified in the On receive action property of the port. Type the following code to detect invalid connections of the machIn port:

if( ! (msg instanceOf Material) ){

Engine.error("Error: The " + this.getFullName() + " port has invalid connection. "); //terminates simulation

}

return true;

This code checks incoming message types. Only messages of Material type sent by prodOut ports are accepted. When a message of another type arrives to the port, the error message is shown.

Another approach consists in transmitting a reference to the sender port along with the message. Having got a reference to a port you can detect a connection with a port of forbidden type by checking the sender’s port type.

Let us demonstrate you how to implement this mechanism. Suppose you have ports of PortA and PortB types in your model and PortA ports can be connected only with the PortB ones. You need to detect invalid connections of the ports of the same type.

Create Message message class with the source field of type Port to carry a reference to message sender port. Specify Message message class in the Message type property of the ports.

To send a message via the port port, you should write the following code in the active object code:

Message msg = new Message();

msg.source = port;

send( msg );

The sent message carries the reference to the sender port.

The checking procedure is specified in the On receive action of the port. For instance, write the following code for the ports of PortA type to allow connections only with the PortB ports:

194

© 1992-2004 XJ Technologies http://www.xjtek.com

AnyLogic V User’s Manual

if (!(msg.source instanceOf PortB))

Engine.error("Error: The " + this.getFullName() + " port is eroneously connected to the " + msg.source.getFullName() + " port." );

}

return true;

This code checks the sender’s port type. The message from non PortB port reception indicates the invalid port connection and the error message is shown.

7.4.9Defining message class constructors

You can initialize the created message data differently, depending on some external conditions. In AnyLogic you create a message instance by calling a message class constructor. The default constructor automatically generated by AnyLogic fills out all the fields of the created message instance in the same order you defined in the Parameters table. However, you may need to create the message with only a certain set of fields. For example, in the distributed database model, the data structure of the server response message depends on the type of the client query. You can define custom message class constructors to create messages with only those message fields that are necessary under the certain conditions.

For example, you need to model an elevator. A user controls the elevator by sending commands to the controller. A command may take a parameter or not, thus the data structure of the created message varies depending on the type of the command. Specifying your own constructors, you can create the command message with certain fields only.

Commands are represented by the messages of the Command class. The message class has the cmd member variable of type String representing the command instruction and the arg member variable representing the optional command argument.

Type Name Default

String cmd

Double arg

The “Move” command takes the parameter, specifying the movement step. In this case the default constructor is used to create the message.

© 1992-2004 XJ Technologies http://www.xjtek.com

195

Chapter 7. Message passing

The default constructor creates a new message with all the fields initialized:

Command ( String cmd, double arg ) {

this.cmd = cmd;

this.arg = arg;

}

However, the “Stop” command does not take any parameters. Thus you can define the custom constructor to create a command message without any parameters. The message class constructor is defined in the Additional class code section of the message class properties:

Command ( String cmd ) {

this.cmd = cmd;

}

Calling different constructors you can create messages with different data structure. For example, the following lines of code create messages, representing “Move” and “Stop” commands correspondingly.

Command movecmd = new Command( “MOVE”, 20.0 );

Command stopcmd = new Command( “STOP” );

In the second case, the custom constructor is called to create the message with the cmd field only.

Note that Java statements you specified in the Constructor code section of the message class properties will be inserted in the default constructor only. Thus this code will be executed only in the case of creating a message instance by the default constructor.

7.4.10Modeling a LIFO queue

The default port queue in AnyLogic is the FIFO queue. However, you may need to model a LIFO queue – e.g., to model a LIFO buffer in queuing models. Messages are extracted from the LIFO queue in the Last-In First-Out order – i.e., the last placed in the queue message is extracted first as shown in Figure 95.

196

© 1992-2004 XJ Technologies http://www.xjtek.com

Соседние файлы в папке AnyLogic