Back home 3.2.1. Predicates down Contents

Token and Data Types
Capacity
Access Modes
Initial Marking
Predicate Properties


Predicates are data containers for dynamic net elements called tokens. The number and type of tokens to be incorporated as well as the mode of token access are defined by the predicates.


3.2.1.1. Token and Data Types top of page down Contents

A predicate can only incorporate tokens of the same data type. Therefore the token type is defined as a property of the predicate. The type of predicate without any token attribution is called place. Such predicates contain tokens which need not differ from one another. Therefore they are called black tokens. Their syntactic designation of a black token is expressed by the $ symbol.

The usable types in Poses++ orientate themselves by the data types of the "C" language (char, short, int, long with the modifiers signed and unsigned, float, double). Most types known from this language can be used with the exception of any pointer types such as char*. Chains of characters are described in Poses++ by the predefined type string (implemented by the C++-class Pos_String in posstr.h),  time values by the predefined type time (implemented by the C++-class Pos_Time in postime.h). Enumerations can be defined  C-like by enum, and structured types by struct. The typedef keyword is also C-like available in Poses++. The predifined data type string offers the + operator to concat two strings and the == operator to compare two strings with a boolean result TRUE if equal.

Examples for predicates

Start example

  typedef string firstname;     // tokentype for predicate P3
  typedef int    numbers;       // tokentype for predikate P4

  enum ColorOfLight { RED, YELLOW, GREEN, REDYELLOW };
                                // tokentype for predicate P5

  struct personnel {            // tokentype for predicate P6
    string name;
    float  bonus;
    struct {
      int                 adge;
      enum {MALE, FEMALE} kind;
    };
  };

  struct TypeCollection {
    char               c;
    signed char        sc;
    unsigned char      uc;
    short int          shi;
    signed short int   sshi;
    unsigned short int ushi;
    int                i;
    signed int         si;
    unsigned int       ui;
    long               l;
    signed long        sl;
    unsigned long      ul;
    float              f;
    double             d;
    string             s;
    time               t;
    enum Enum {
      E1=1,
      E2,
      E3
    }                  e;
    struct Struct {
      char      a,b,c;
      personnel person;
    }                  abc_person;
    numbers            n;
  };

End example

The binary representation of all data types depents from the hardware and the operating system your simulation server is running on.


3.2.1.2. Capacity up down Contents

The capacity, which is a property of predicates, defines the maximum number of tokens a predicate can incorporate simultaneously. The standard capacity is infinite which means for Poses++ exactly 2^32 - 1 = 4294967295. The lowest permissible capacity is 1.

All modelling elements in Poses++ are based on module types. Thats why the following source code examples use the module syntax.

Start example

  // valid definitions for predicate capacities
  #define MAX 4294967295
  #define MIN 1

  // capacity as adjustable parameter
  module CapacityExamples {

  public:

    const unsigned long Parameter = MAX;

  private:

    // a type declaration for a place with maximal "Parameter" tokens:
    typedef place<Parameter> PlaceType;

    // a type declaration for a place with maximal one token:
    typedef place<MIN>       FlagType;

    place<Parameter  >       P1; // a place with in maximum "Parameter" black tokens
    PlaceType                P2; // capacity from data type "PlaceType"
    place<P1.capacity>       P3; // capacity identical to P1.capacity
    place                    P4; // a place with infinite capacity (in practice: 2^32)
    FlagType                 P5; // a place with 1 token capacity

    /* the following source would produce an error because expressions are
       not allowed to define the capacity of a predicate:

    place<MAX-MIN>           P6; // Error: ... ">" expected
    */
    // to avoid this error you can specify:
    const unsigned long CAP = MAX - MIN;
    place<CAP> P6;
  };

End example


3.2.1.3. Access Modes up down Contents

The access mode of a predicate defines how the tokens are to be filled into a predicate, and in what sequence they are searched. The following access modes are available:

BUFFER

This is the basic and simplest token access mode. The internally implemented mechanism is the same like for FIFORAM. During the search process, tokens may be found which are not in the first position of the searching sequence. This automatically results in a principle which gives preference to the oldest tokens of the predicate. The buffer access mode is the fastest mode and so mostly the best choice.
RAM

The tokens are filled at random within the predicate. During the search process in order to meet the fire rule for a transition the order of tokens is not changed. In every search process the token order is different which corresponds with the random access principle.
FIFO

Those tokens which were filled first into the predicate are the first ones in searching sequence. Their positions in the token order do not change. The tokens in the following positions can only be removed after the first one has been removed. This is the first-in-first-out principle.
LIFO

Those tokens which were filled last into the predicate are the first ones in the searching sequence. Their positions in the token order do not change. The tokens in the following positions can only be removed after the first one has been removed. This is the last-in-first-out principle.
FIFORAM

The FIFO access mode is applied. During the search process, tokens may be found which are not in the first position of the searching sequence. This automatically results in a principle which gives preference to the oldest tokens of the predicate. The fiforam access mode is identical to the buffer access mode.
LIFORAM

The LIFO access mode is applied. During the search process, tokens may be found which are not in the first position of the searching sequence. This results in a principle which gives preference to the youngest tokens of the predicate.

Which of the above mentioned access modes is selected depends on  the problem you want to solve. If you believe it doesn't matter select buffer at first. Predicates of the place type automatically apply the RAM mode because they contain black tokens which cannot be differed from each other and, therefore, it does not matter whether a token is older or younger than others.

Start example

module AccessModeExamples {

  // a common predicate with token type int and capacity=5:
  buffer  <int,5> BufferInt;

  // a random access predicate with token type int and capacity=3:
  ram     <int,3> RamInt;

  fifo    <int,3> FifoInt;
  lifo    <int,3> LifoInt;
  fiforam <int,3> FifoRamInt;
  liforam <int,3> LifoRamInt;
  place   <    3> Place;

  // without capacity specifications:
  buffer  <int  > RamIntUnlimited;
  place           PlaceUnlimited;

};

End example


3.2.1.4. Initial Marking down down Contents

A model is not only described by predicates, transitions and arcs. The behaviour of the net the model is based upon is also defined by its initial marking i.e., the initial token constellation within the predicates:

Examples for predicates

Poses++ makes available constant arc expressions to define a initial marking for a predicate.

Start example

module InitialMarkingExample {

  enum Color { // definition of token type "Color":
    RED,
    YELLOW,
    GREEN,
    BLUE
  };

  struct Person {
    string   Name;
    unsigned Age;
  };

  place  <25    > Counter << card(4),$;            // 4 black tokens initialized
  fiforam<string> Names   << "Otto"
                          << "Anna"
                          << "Paul";               // 3 string tokens initialized
  ram    <Color>  Colors  << BLUE << RED << GREEN; // 3 colors initialized
  lifo   <Person> Persons << {"Andrae",35}
                          << {"Bert"  ,36};
};

End example

Another way to parametrize a model with the necessary start situation you have using command files. There you can spezify a command like PutToken PredicateName TokenValue. Different to the C-like syntax conventions in Poses++ source code the token value have to specified TCL-conform:

PutToken InitialMarkingExample.persons {"Andrae" 35}
PutToken InitialMarkingExample.persons {"Bert"   36}

The entries in such a command file will be sent to the simulation server typically after loading the model and the server will execute this commands which results in the same data situation like reached via initial marking expressions.


3.2.1.5. Predicate Properties up end of page Contents

Every predicate instance has the predefined properties capacity, card, reserve, name and path. The writable property capacity specifies the amount of tokens the predicate can hold at maximum (see also: Capacity). The read only property card on one hand specifies the actual count of token in that predicate and the property reserve specifies the amount of tokens the predicate is able to get. The context is not every time capacity = card + reserve because future events for this predicate or output arcs of the same transition can occupy buffer space not belonging to card or to reserve. These three properties are based on the data type unsigned long int.

Start example

module PrecicatePropertyExample {

  place<10> P;

  trans Clear { // clear all tokens in one fire step
    P >> card(P.card),$;
    action {
      P.capacity = P.capacity + 1;
    }
  }

  trans Fill {  // fill the free place in one fire step
    P << card(P.capacity), $;
  }

  trans FillRest {  // fill the rest of possible tokens
    P << card(P.reserve), $;
  }
};

End example

The property name specifies the real instance name of this module instance and path the real full instance name including all parent names of that module instance. Both non writable properties are based on the data type string. These both properties are identical to the properties of module instances (see also: Module Properties).


Back home mail copyright © Andrae Behrens 05/24/2023
up Contents