Page tree
Skip to end of metadata
Go to start of metadata

Event interactions

One of the powers of MP is the ability to specify system behaviors individually and then specify interactions between the systems of interest as a separate set of constructs.   The prior examples in this tutorial have been about individual systems (chains of events involving a single "actor").  Of interest in complex problems is the interaction between systems (subsystems, actors, components) and resulting complex behavior including possibly emergent behavior.

Most processes involve multiple actors, where each performs their own activities. Usually such actors are modeled as root events. In order to accomplish the whole task, actors (or components) often should interact. MP provides high level abstractions  for modeling interactions – composition operations COORDINATE and SHARE ALL. These abstractions hide the implementation details and focus on the modeling the fact of interaction, or dependency between activities performed by root events. 

Let's start another set of examples with preloaded Example 1 from firebird.nps.edu.  This example is available from the Import Button.

SCHEMA simple_message_flow

ROOT Sender:   (* send *);

ROOT Receiver: (* receive *);

COORDINATE              $x: send           FROM Sender,

                                             $y: receive FROM Receiver

               DO ADD $x PRECEDES $y; OD;

Example 11 Two Independent ROOTs

This example introduces several new concepts: variables ($x, $y: MP section 5.2), navigation directions (FROM, PRECEDES: MP section 5.5), coordination of events (COORDINATE, DO…OD: MP section 5.6), adding a relationship (ADD)

COORDINATE composition operation

COORDINATE is a composition operation because what it does is cause the previously independent ROOTs to merge and produce a single set of behaviors (traces).

Running the example at scope 2 produces three traces.   If you use the Help feature on Firebird, you will see the black arrows listed as "FOLLOWS" where the example specified PRECEDES.  As noted in section  5.5 of the MP Syntax Manual, names for expressions which can be derived from the two basic MP relationships (IN and PRECEDES) are listed.  As would be expected, FOLLOWS is the reverse (~) of PRECEDES.   It should be noted that ADD (section 5.6 of MP Syntax Manual) only permits specification of relationships IN and PRECEDES between the events.   Predefined relationships listed in Section 5.5 (such as FOLLOWS) can only be used in the circumstances specifically listed.  Attempts to use elsewhere (such as in ADD) will result in a syntax error.   The reasoning for this is discussed in the later on in the tutorial.

Figure 14 Send-Recieve coordination scope 2

Variables in MP

Variables in MP can be assigned events instances as values using the $variable_name syntax.  

 

From the MP Manual Section 5.5:

 

variable: $Id;

MP variable is an identifier preceded by ‘$’, like $a, and can be assigned an event instance as a value. It can be used in several MP constructs: thread(26), shared_composition(28), coordination_source(32), add_relation(36), map_unit(39), bool_expr3(57), event_instance(64), special_function(65).

 

In the above example, the variables $x and $y are used to stand for the send and receive events so that their interaction can be specified via the COORDINATE DO…OD syntax.

Since the source (ROOT) of each variable is defined using the keyword FROM, as long as the variables  have unique names, the event names in the ROOTs do not have to be unique.   If the names are unique, the keyword FROM can be omitted.   Attempts to define variables outside of the above constructs will result in a syntax error.  Unlike conventional programming languages, all variables are forced to be local through MP syntax and cannot be made global by positioning them higher in the file.

SHARE ALL composition operation.

SHARE ALL also allows "coordination" of events, however it forces events to be mutual rather than specifying an ordering or inclusion between events in different roots (which is what COORDINATE … PRECEDES…  does).  Refer to the MP Manual Section 5.6 (28).  Let's revisit the student example (simplified) and introduce a friend.

 

ROOT Serious_Student: (+ Attend_class +)

  [(Go_to_library|Visit_with_friends)];

ROOT Casual_Student: (* Think_about_class *)

               [ Attend_class] Visit_with_friends;


Example 12 Independent Students

 

Figure 15 Independent Students Undesired Behavior Trace # 10

Notice the (probably) undesired behavior of attending class without even thinking about it first in the case of the casual student.  Further notice that we can use "Attend_class" and Visit_with_friends in both ROOTs without either causing conflict or coordination.  This is a similar idea of the scoping of variables private to a file or function in conventional programming languages.

 

To fix the (probably) undesired behavior the code for Casual_Student can be changed to force Attend_class to happen only if you have thought about it first:

 

ROOT Serious_Student: (+ Attend_class +)

  [(Go_to_library|Visit_with_friends)];

ROOT Casual_Student: (* Think_about_class [ Attend_class] *)

                Visit_with_friends;

Suppose our intention is to model events so that both students are attending the same class and are visiting with the same friends (mutual events).  In the example above, even though the event names are the same, the events in question are actually independent.  The intention can be accomplished by merging the traces using SHARE ALL as in the example below:

 

ROOT Serious_Student: (+ Attend_class +)

  [(Go_to_library|Visit_with_friends)];

ROOT Casual_Student: (* Think_about_class [ Attend_class] *)

                Visit_with_friends;

Serious_Student, Casual_Student   SHARE ALL  Attend_class, Visit_with_friends;

 

Note that if you do a SHARE ALL when the event only exists in one of the ROOTs it is syntactically valid, but will create no traces, so be sure that your events intended to be mutual are identically spelled.  (recall that MP is case sensitive).    Pulling the events on the GUI allows you to see the mutual events.

 

Example 13 SHARE ALL

Figure 16 SHARE ALL scope 1

A single trace is created.  Notice that when an event is optional for one of the ROOTs and not for the other, the merged trace has the shared event as non-optional.  This effectively means that the alternative of Go_to_library is precluded for the serious student by the forced sharing since Visit_with_friends always happens for the casual student.  Also the casual student always attend class by the same reasoning:  whenever the serious students attends class, the casual student must also attend class.

When this is run at scope 2, four traces are generated.  Notice that the casual student can think about class without attending up to scope -1 times, but has to go to class eventually.  The serious student still cannot go to the library due to the shared event of visit with friends.

Since the desired behavior is to have the student able to opt for the library, we try the following code:

 

ROOT Serious_Student: (+ Attend_class +)

  [(Go_to_library|Visit_with_friends)];

 

ROOT Casual_Student: (* Think_about_class [ Attend_class] *)

                Visit_with_friends;

Serious_Student, Casual_Student   SHARE ALL  Attend_class;

 

Notice that the casual student must still eventually attend class at least once since the serious student always does so. 

 

 

Figure 17  Think before attending

In the above trace the serious student's activity terminates with attending class (no visiting and no library)  in this trace.  This can be discerned by attending to the grey arrows (which show inclusion).  As seen in trace 9 below, the activities of Visit_with_friends are now independent.  Also, the casual student attends class the same number of times as the serious student.  In this trace the casual student is running through two iterations where the casual student runs only through one.  Recall that the traces produce all possible combinations of behavior (including iterating).

Figure 18 Less sharing

In the independent student example suppose you want to have the serious student visit with friends only if the casual student calls.  One way to do this is to use COORDINATE .   Notice that the SHARE ALL needs to be removed from the prior example in order see traces where the serious student does not visit with friends.

 

ROOT Serious_Student: (+ Attend_class +)

  [(Go_to_library|Visit_with_friends)];

ROOT Casual_Student: (* Think_about_class [Phone_friends] [ Attend_class] *)

                Visit_with_friends;

COORDINATE

    $a:  Visit_with_friends FROM Serious_Student,

    $b:  Phone_friends FROM Casual_Student

    DO

                   ADD $b PRECEDES $a;

  OD;    

 

Example 14 Two Students with Phone A Friend

Notice now from the traces  that the only way that the Serious student can visit with Friends is if the casual students phones ahead.

SUCH THAT condition, transitive closure and reverse relationships

Sometimes coordination is desired with restrictions or conditions.  This can be accomplished by using the SUCH THAT construct to specify the conditions.  It is important to note that SUCH THAT does not pick up precedence conditions within a given root and should not be used to try and preclude optional events. Besides such precedence is obvious from the model construct so if you need to "filter it out" then it should be just removed from the model (maybe temporarily via commenting out).  SUCH THAT is used to filter on relationships between ROOTs.

Recall that there are only two basic relationships between events in MP, inclusion and precedence which are indicated by IN and PRECEDES, respectively.  Due to the possibility of nested relationships and chaining of precedence,  the concepts  of the transitive property (the same thing as from your algebra I class) and closure are necessary.

A note about Navigation Directions (section 5.5 in the MP manual)

We have covered PRECEDES in the examples and will be covering IN during subsequent sections of this tutorial.   All of the other navigation direction keywords (BEFORE, AFTER…) are either the reverse (~) or transitive closures (^)  or both (~^) of IN or PRECEDES.   ~ and ^ cannot be directly applied to IN or PRECEDES: the applicable constructions from 5.5 must be used.

Just in case you have not taken algebra in a while and forgot what a transitive closure is, you can think of  the subset Ì relationship as an example.  That is:  if  a Ì b and b Ì c , this implies that a Ì c.  Which is the transitive part.  The closure comes in where c is the largest applicable set. 

Extending the previous example to add conditions under which the precedence must take place:

 

ROOT Serious_Student: (+ Attend_class +)

  [(Go_to_library|Visit_with_friends)];

ROOT Casual_Student: (* Think_about_class [Phone_friends] [ Attend_class] *)

                Visit_with_friends;

COORDINATE

    $a:  Visit_with_friends FROM Serious_Student,

    $b:  Phone_friends FROM Casual_Student

                              SUCH THAT $a AFTER $b

    DO

                              ADD $b PRECEDES $a;

  OD;    

Example 15 Adding in SUCH THAT in a not so helpful way

When this is run, you actually get more traces than before, not less!   This is because the SUCH THAT condition is imposed before any coordination  has a chance to be added and Serious Student also can't visit with friends since that is now precluded by the SUCH THAT condition.   SUCH THAT needs to be applied after ROOTs have been merged in some way.

For a more extensive example involving SUCH THAT, refer to the Publish_Subcribe model available from the import menu on Firebird.

Sets of Events, BUILD, Nested COORDINATE  and One-Many Coordination.

The Car_Race example on Firebird provides a nice illustration of the way in which MP can be used to model many (cars) to one (judge for the race) system interations and nested coordination.   It also contains a number of other constructs covered in this tutorial (as well as a number which are not).  An eclipsed version of the model is shown with additional commentary inserted.

 

SCHEMA Car_Race

ROOT Cars:    {+ Car +}    

 

/* One or more instances of Car appear in the model dictated by the scope at which the model is being run: that is you have specified an un-ordered set of events.  This is in contrast to the (+ Car +) syntax which creates a sequence (i.e. ordered set) of events.  The BUILD statement is required to specifiy how the events comprising Cars relate to one another.  Syntactically the BUILD statement can be empty (which might be a good first cut for model debugging).   From the MP Manual Section 2.6

 

" The BUILD block associated with a root or composite event contains composition operations performed when event trace segment representing the behavior of that root or composite is generated."

 

                                             BUILD{

                                                            ………/*items in here specify how

                                                                           the cars relate to each other*/

                                             };

 

/*now we have the event definitions for each car

               Car:      start

                                             (* drive_lap *)

                /* not necessary all cars will finish */

                                             ( finish [ winner ] | break) ;

                                                           

ROOT Judge:                provide_start_signal

                                                            watch 

                                                            (* finish *);

 

/* one-many coordination can be done with nested COORDINATE */

/*The outer coordinate is from the one and the inner coordinate uses the <!> notation which indicates asynchronous coordination of the cars (many)*/

 

COORDINATE              $a: provide_start_signal      FROM Judge

               DO        COORDINATE <!> $b: start FROM Cars

                                             DO ADD $a PRECEDES $b; OD;

               OD;

              

Cars, Judge SHARE ALL finish;

 

/*          now when the ordering of finish events is ensured

               we can state: the winner is the car which finishes first */

/*since winner only applies to the cars, the FROM can be omitted

COORDINATE $w: winner

               /*# indicates the number of that event type in the trace

               DO ENSURE #finish BEFORE $w == 1; OD;

 

/* this is an example of a query annotating the trace with data

               specific for the trace */

               SAY(#finish " cars have finished");

Example 16 Car Race example with commentary added

BUILD can also be used in a non-nested context to construct sets of rules without multiple ROOT generation.

 

  • No labels