Anda di halaman 1dari 41

jMarkov User's Guide

Germn Riao and Julio Gez Universidad de Los Andes


Contents

1 Introduction 2 Building Large - Scale Markov Chains


2.1 2.2 Space state building algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Measures of Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2 2
3 3

3 Framework Design
3.1 3.2 3.3 3.4 Java and Object Oriented Programming . . . . . . . . . . . . . . . . . . . . . . . . . Build Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Basic Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Solvers Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4
4 4 5 6

4 Examples
4.1 Example: An M/M/2/N with dierent servers . . . . . . . . . . . . . . . . . . . . . . 4.1.1 4.1.2 4.1.3 4.1.4 4.2 4.2.1 4.2.2 4.3 4.3.1 4.3.2 The model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Class QueueMM2dNState . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Class QueueMM2dN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Results

6
6 6 7 7 7 13 13 14 21 21 32

Multiple Server Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Drive Thru

5 Modeling Quasi-Birth and Death Processes


5.1 5.2 5.3 5.4 Quasi-Birth and Death Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Measures of performance for QBDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modeling QBD with jQBD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . An Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

33
34 35 35 35

6 Advanced Features
6.1 6.2 6.3 6.4 Using the Solvers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the Transitions scheme extending jMarkov . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Computing MOPs on the y to save memory

37
37 37 37 37

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7 Further Development References


1

37 37

Introduction

The jMarkov project has been in development since 2002 by the research grup COPA at Universidad de los Andes. The main purpose of jMarkov is facilitating the development and application of large sacale Markovian models, so that they can be used by engineers with basic programming and stochastic skills. The project is composed by four modules

jMarkov jQBD jPhase jMDP

In this manual we explain jMarkov and jQBD, which are used to build Markov Chains and Quasi-Birth and death processes (QBD). The other two modules have their own manulas. With jPhase a user can easily manipulate Phase-Type distributions (PH). These distibutions are quite exible and powerful, and a model that is limited to PH in practical terms can model many situations. For details see [8] and [7] jMDP is used to build and solve Markov Decision Process (MDP).MDP, or, as is often called, Probabilistic Dynamic Programming allows the analyst to design optimal control rules for a Markov Chain.jMDP works for discrete and continous time MDPs.For details see [11] and [10] For up-to date information, downloads and examples check COPA's web page at

edu.co.
2 Building Large - Scale Markov Chains

copa.uniandes.

In this section, we will describe the basic algorithms used by jMarkov to build Markov Chains. Although we limit our description to Continuous Time Markov Chain (CTMC), jMarkov can handle also Discrete Time Markov Chains (DTMC). Let nents

{X (t), t 0}

be a CTMC, with nite space state

and generator matrix

Q,

with compo-

qij = lim P {X (t) = j |X (0) = i}


t0

i, j S .

It is well known that this generator matrix, along with the initial conditions, completely determines the transient and stationary behavior of the Markov Chain (see, e.g, [4]). The diagonal components

qii

are non-positive and represent the exponential holding rate for state

i,

whereas the o diagonal

elements

qij

represent the transition rate from state

to state

j. P(t)
with components

The transient behavior of the system is described by the matrix

pij (t) = P {X (t + s) = j |X (s) = i}


This matrix can be computed as

i, j S .

P(t) = eQt
For an irreducible chain, the stationary distribution to the following system of equations

t > 0. = [1 , 2 , . . . , ]
is determined as the solution

Q = 0 1 = 1,
where

is a column vector of ones.

2.1 Space state building algorithm


Transitions in a CTMC are triggered by the occurrence of events such as arrivals and departures. The

Q can be decomposed as Q = eE Q(e) , where Q(e) contains the transition rates associated with event e, and E is the set of all possible events that may occur. In large systems, it is not easy to
matrix know in advance how many states there are in the model. However, it is possible to determine what events occur in every state, and the destination states produced by each transition when it occurs. jMarkov works based on this observation, using an algorithm similar to the algorithm buildRS presented by Ciardo [1]; see Figure 1. The algorithm builds the space state and the transition rate by a deep exploration of the graph. It starts with an initial state i0 and searches for all other states. At every instant, it keeps a set of unchecked states not been previously found, they are added to the calling the function and the functions

and the set of states

that have been already

checked. For every unchecked state the algorithm nds the possible destinations and, if they had

set. To do this, it rst calls the function

active
. From

that determines if an event can occur. If it does, then the possible destination states are found by

dests

. The transition rate is determined by calling the function

rate

this algorithm, we can see that a system is fully described once the states and events are dened

active, dests, and rate have been specied.

As we will see, modeling a problem

with jMarkov entails coding these three functions.

S = , U = {i0 }, E given. while U = do for all e E do if active(i, e) then D := dests(i, e) for all j D do if j / S U then U := U {j }

end if

end for end if end for end while

Rij := Rij + rate(i, j, e)

Figure 1: BuildRS algorithm

2.2 Measures of Performance


When studying Markovian systems, the analyst is usually interested in the transient and steady state behavior of measures of performance (MOPs). This is accomplished by attaching rewards to the model. Let receives

r be a column vector such that r(i) represents the expected rate at which the system rewards whenever it is in state i S . Here the term reward is used for any measure of

performance that might be of interest, not necessarily monetary. For example, in queueing systems

r(i)

might represent the number of entities in the system,or the number of busy servers, when the

state is

i.

The expected reward rate at time

is computed according to

E r(X (t) = aP(t)r,


where the row vector calculated as

has the initial conditions of the process (i.e.,

ai = P {X (0) = i} , i S ).

Similarly, for an irreducible CTMC, the long run rate at which the system receives rewards is

1 t t lim

E r(X (s) ds = r.
0
3

Build Package
MarkovProcess SimpleMarkovProcess GeomProcess

Basics Package
JMarkovElement PropertiesElement Event PropertiesEvent State GeomState GeomRelState PropertiesState

Solvers Package
Solver SteadyStateSolver GeometrixtSolver TransientSolver JamaSolver JamaTransientSolver MtjSolver MtjLogRedSolver

Figure 2: Class classication

As we will see, jMarkov provides mechanisms to dene this type of rewards and can compute both, transient and steady state MOPs. There are other type of rewards, like expected time in the system, which can be easily computed using Little law.

Framework Design

In this section, we give a brief description of jMarkov's framework architecture. We start by describing object-oriented programming and then describe the three packages that compose jMarkov.

3.1 Java and Object Oriented Programming


Java is a programming language created by Sun Microsystems [12]. The main characteristics that Sun intended to have in Java are: Object-Oriented, robust, secure, architecture neutral, portable, high performance, interpreted, threaded and dynamic. Object-Oriented Programming (OOP) is not a new idea. However, it did not have an increased development until recently. OOP is based on four key principles: abstraction, encapsulation, inheritance and polymorphism. An excellent explanation of OOP and the Java programming language can be found in [13]. The abstraction capability is the one that interests us most. Java allows us to dene abstract types like

MarkovProcess, State, etc.

We can also dene abstract functions like

active, and dests.

We can program the algorithm in terms of these abstract objects and functions and the program works independently of the particular implementation of the aforementioned elements. All the user has to do is to implement the abstract functions. What is particularly nice is that if a function is declared as abstract, then the compiler itself will force the user to implement it before she attempts to run the model.

3.2 Build Package


The build package is the main one in jMarkov since it contains the classes that take care of building the state space and transition matrices. The main classes are

Process,
processes,

and

GeomProcess (see Figure 3). Whereas the rst two allow to model general Markov GeomProcess is used for Quasi-Birth and Death Processes (QBD) and its description is

MarkovProcess, SimpleMarkov-

given in Section 5.3 below. methods that implement the three aforementioned functions in the algorithm BuildRS:

SimpleMarkovProcess represents a Markov chain process, and contains three abstract active, dests, and rate. In order to model a problem the user has to extend this class and implement the three functions. An example is given in Section 5.4. The class MarkovProcess is the main class in
The class the module, and provides a more general mechanism to describe the dynamics of the system. It also contains tools to communicate with the solvers to compute steady state and transient solutions, and print them in a diverse array of ways. For details, see [9].

MarkovProcess

SimpleMarkovProcess

GeomProcess

Figure 3: Class diagram build module

3.3 Basic Package


This package contains the building blocks needed to describe a Markov Chain. It contains classes such as

State,

and

Event,

which allow the user to code a description of the states and events,

respectively (see Figure 4). The user has freedom to choose any particular coding that best describes the states in her model, like any combination of integers, strings, etc. However, she must establish a complete ordering among the elements since, for eciency, jMarkov works with ordered sets. For simplicity, however, a built-in class is provided, called there is an analogous class called and

PropertiesState,

that describes the state

with an array of integers, something which is quite appropriate for many applications. Similarly,

Events

PropertiesEvent.

The package also contains the classes

States

that are used to describe collections of states and events.

These are fairly general

classes, since all that is required from the user is to provide a mechanism to walk through the elements of the set, taking advantage of Java iterator mechanism. This implies that, for large sets, there is no need to generate (and store) all the elements in the set. For convenience, the package provides implementations of these set classes based on sorted sets classes available in Java.

<<Interface>> JMarkovElement

State

<<Interface>> PropertiesElement

Event

GeomState

GeomRelState

PropertiesState

PropertiesEvent

Figure 4: Class diagram for the basic package

3.4 The Solvers Package


As stated above, jMarkov separates modeling from solving. steady-state and transient probabilities (see Figure 5). Various solvers are provided to nd If the user does not specify the solver to use, one is provided by default. However, the architecture is exible enough to allow an interested user to choose a dierent solver, or, if she desires, to implement her own. The basic class is called

Solver,

that has two sub-classes called

SteadyStateSolver, TransientSolver,

and

GeomSolver

(see Figure 5). As the names indicate, the rst two provide solvers for steady state and transient probabilities, whereas the latter is used for QBDs, as explained in section 5. The implementations provided relay on two popular Java packages to handle matrix operations JAMA [3] and MTJ [2], for dense and sparse matrices, respectively.

Solver

TransientSolver

SteadyStateSolver

GeometrixtSolver

JamaTransientSolver

JamaSolver

MtjSolver

MtjLogRedSolver

Figure 5: Class diagram of the solvers package

Examples

4.1 Example: An M/M/2/N with dierent servers


Assume that a system has Poisson arrivals with rate

There are two exponential servers with rates

and

respectively. There is a maximum of

customers in the system. An arriving customer

that nds the system empty will go to server 1 with probability available server, or join a single FCFS queue. If there are

Otherwise he will pick he rst

in the system the customer goes away.

4.1.1 The model


We model this system with the triple the status of the server (1 if busy 0 otherwise) and

X(t) = (X (t), Y (t), Z (t)), where X (t) and Y (t) represents Z (t) represents the number in queue, which is a number from 0 to N 2. There are 2 2 N 2 potential states, however not all combinations of X, Y and Z are possible. For example the state (0, 1, 2) is not acceptable since we assume that
a server will not be idle if there are people in the queue. The set of states will be of the form

S = {(0, 0, 0), (0, 1, 0), (1, 0, 0)} {(1, 1, k ) : k = 0, 1, . . . , N 2}


The transition matrix will have the form

000 000 010 100 110 111 112 . . . 1,1,N-3 1,1,N-2

010

100

110

111

112

...

1,1,N-3

1,1,N-2

2 1 1

(1 ) 2 1 + 2 1 + 2

4.1.2 Class QueueMM2dNState


Our characterization of each state ts nicely as a particular case of the PropertiesState class with three properties. Since we decided to work with numbered events rather than extending the Event class, we should implement the model the State with the class

QueueMM2dN.

SimpleMarkovClass. In the following code you will see how we rst QueueMM2dNState and then model the system implementing the class

These two class are placed in the same le QueueMM2dN, but they could be placed

in separate les. To model the State we begin by creating a constructor that assigns x, y, and z to the properties. We provide methods to access the three properties and a method to check whether the system is empty. We also implement the method label to override the one in the class PropertiesState.

4.1.3 Class QueueMM2dN


There are two basic events that can occur: arrivals and service completions. We have to distinguish, however two types of service completions depending on whether the server that nishes is 1 or 2. Also, when the system is empty we have to distinguish between arrivals that go to server 1 and those that go to server 2. So in total we have ve events which we number as follows

4.1.4 Code
File QueueMM2dN.java

package import import import import import import import import import import
// Lets

examples . jmarkov ;

java . i o . BufferedReader ; java . i o . IOException ; java . i o . InputStreamReader ;

jmarkov . MarkovProcess ; jmarkov . SimpleMarkovProcess ; jmarkov . b a s i c . Event ; jmarkov . b a s i c . E v e n t s S e t ; jmarkov . b a s i c . P r o p e r t i e s S t a t e ; jmarkov . b a s i c . S t a t e s ; jmarkov . b a s i c . S t a t e s S e t ;

start

defining

the

State

This i s a p a r t i c u l a r c a s e o f p r o p e r t i e s S t a t e , whith t h r e e p r o p e r t i e s , n a m e l y t h e s e r v e r 1 and 2 s t a t u s , p l u s t h e q u e u e @ a u t h o r Germn R i a o . U n i v e r s i d a d d e l o s Andes .


7

level .

class
/

MM2dNState

extends

PropertiesState

We i d e n t i f y e a c h S t a t e w i t h t h e t r i p l e t a r e t h e s t a t u s o f t h e s e r v e r s and z t h e . . , N 2 ) . /

(x , y , z ) , number in

where queue

and (0 ,1 ,

MM2dNState (

int x , int y , int z ) { super ( 3 ) ; / / C r e a t e s a P r o p e r t i e s S t a t e this . p r o p [ 0 ] = x ; this . p r o p [ 1 ] = y ; this . p r o p [ 2 ] = z ;

with

properties .

public void

@Override

computeMOPs ( M a r k o v P r o c e s s " Status " Status " Queue " Number Server Server Length " , in 1" , 2" ,

mp)

setMOP ( mp , setMOP ( mp , setMOP ( mp , setMOP ( mp , }

getStatus1 ( ) ) ; getStatus2 ( ) ) ;

getQSize ( ) ) ; getStatus1 () + getStatus2 () + getQSize ( ) ) ;

System " ,

public int return


} /

Returns @return /

the

status of

of the

the

first

Server

Status

first

Server

getStatus1 () prop [ 0 ] ;

public int return


} /

Returns @return /

the

status of

of the

the

second

Server

Status

second

Server

getStatus2 () prop [ 1 ] ;

public int return


} /

Returns @return /

the

size of

of

the

queue of the queue

Status

the

size

getQSize ( ) prop [ 2 ] ;

boolean i s E m p t y ( ) { return ( g e t S t a t u s 1 ( )
}

i s E m p t y d e t e c t s i s t h e s y s t e m i s empty . I t c o m e s handy when c h e c k i n g w h e t h e r t h e e v e n t s ARRIVAL1 and ARRIVAL2 a r e a c t i v e /


+ getStatus2 () + getQSize ( ) = = 0);

@see /

j m a r k o v . b a s i c . S t a t e#i s C o n s i s t e n t ( )

public boolean
}

@Override

isConsistent ()

return true ;
/

// T O D O Complete

We ... /

implement , N

label

so

that

States

are

labeld

1,

1A ,

1B ,

2,

3,

public if if if
}

@Override String stg

label ( )
= "0" ; " 1A" ;

String

(( getStatus1 () stg =

= =

1)

& &

( getStatus2 ()

= =

0))

(( getStatus2 () stg = " 1B" ;

= =

1)

& &

( getStatus1 ()

= =

0))

(( getStatus2 () stg = "" + (2

= = +

1)

& &

( getStatus1 ()

= =

1))

return
/

getQSize ( ) ) ;

stg ;

This /

method

gives

verbal

description

of

the

State .

public

@Override String stg description () = "" ; 1 is 2 are " is " + " + (( getStatus1 () + = = 1) ? 1) " busy " ? : "idle" ); : "idle" ); in queue . " ; {

String stg stg stg

+ = " Server + = ". + = ".

Server There

(( getStatus2 () + "

= =

" busy " waiting

return
} }

getQSize ( )

customers

stg ;

class
/

QMM2dNEvent

extends
/
{

Event

public
/ /

Event

types Type

enum An

arrival

/
server 1 ( only for emtpy system )

ARRIVAL, Arrival to

/ /

ARRIVAL1 , / Arrival to server 2 ( only for emtpy system )

ARRIVAL2 , / departure from server 1

/ /

DEPARTURE1, / departure from server 2

DEPARTURE2 ; }

private
/

Type

type ;

public QMM2dNEvent ( Type super ( ) ; this . t y p e = t y p e ;


} /

@param /

type

type )

public f i n a l Type return t y p e ;


} /

@return /

Returns

the

type .

getType ( )

public s t a t i c for
( Type

@return /

the

set

of

all

events .

EventsSet< QMM2dNEvent > evSet =

EventsSet< QMM2dNEvent > type

new

getAllEvents ()

EventsSet< QMM2dNEvent> ( ) ;

return
} }

e v S e t . add ( evSet ;

new

Type . v a l u e s ( ) ) QMM2dNEvent ( t y p e ) ) ;

//

Now

we

define

main

the

class

This c l a s s r e p r e s e n t s i s a system with 2 d i f f e r e n t s e r v e r s w i t h r a t e s mu1 and mu2 , r e s p e c t i v e l y , and lambda . @ a u t h o r Germn R i a o . U n i v e r s i d a d d e l o s Andes . /
QueueMM2dN

exponential arrival rate

public c l a s s
//

extends

S i m p l e M a r k o v P r o c e s s <MM2dNState ,

QMM2dNEvent >

f i n a l int ARRIVAL = 0 ; f i n a l int ARRIVAL1 = 1 ; / / o n l y f i n a l int ARRIVAL2 = 2 ; / / o n l y f i n a l int DEPARTURE1 = 3 ; f i n a l int DEPARTURE2 = 4 ; private double lambda ; private double mu1 , mu2 , a l p h a ; private int N ;

Eventos

for for

emtpy emtpy

system system

public QueueMM2dN ( double lambda , double super ( ( new MM2dNState ( 0 , 0 , 0 ) ) , / /


10

C o n s t r u c t s a M/M/ 2 d q u e u e w i t h a r r i v a l r a t e lambda and s e r v i c e r a t e s mu1 and mu 2 . @param lambda A r r i v a l r a t e @param mu1 S e r v e r 1 r a t e @param mu2 S e r v e r 2 r a t e @param a l p h a P r o b a b i l i t y o f an a r r i v i n g c u s t o m e r c h o o s i n g server 1 ( i f both idle ) @param N Max number i n t h e s y s t e m /
mu1 ,

double

mu2 ,

double

alpha ,

int

N)

this . lambda = lambda ; this . mu1 = mu1 ; this . mu2 = mu2 ; this . a l p h a = a l p h a ; this . N = N ;
} /

QMM2dNEvent . g e t A l l E v e n t s ( )

);

//

num

Events

public QueueMM2dN ( ) { this ( 1 . 0 , 2 . 0 , 3 . 0 ,


} /

R e t u r n s an QueueMM2N o b j e c t w i t h a r r i v a l r a t e 4 . 0 , s e r v i c e o f the f i r s t s e r v e r 2 . 0 , s e r v i c e r a t e o f the second s e r v e r p r o b a b i l i t y o f c h o o s e t h e f i r s t s e r v e r 0 . 3 and c a p a c i t y o f c u s t o m e r s i n t h e s y s t e m . Used by GUI /


0.3 , 8);

rate 3.0 , 8

public @ O v e r r i d e boolean a c t i v e ( MM2dNState boolean r e s u l t = f a l s e ; switch ( e . g e t T y p e ( ) ) { case ARRIVAL : case case break ; break ; break ; case case
} result result result result = ( ( i . getQSize ( ) < N

Determines /

the

active

events

i ,

QMM2dNEvent

e)

2)

& &

( ! i . isEmpty ( ) ) ) ;

ARRIVAL1 : = i . isEmpty ( ) ;

ARRIVAL2 : = i . isEmpty ( ) ;

DEPARTURE1 :

break ; break ;
result

( i . getStatus1 ()

>

0);

DEPARTURE2 : = ( i . getStatus2 () > 0);

return

result ;

public @ O v e r r i d e S t a t e s <MM2dNState> int newx = i . g e t S t a t u s 1 ( ) ; int newy = i . g e t S t a t u s 2 ( ) ; int newz = i . g e t Q S i z e ( ) ; switch ( e . g e t T y p e ( ) ) { case ARRIVAL : i f ( i . getStatus1 ()
newx = } 1; desocupado = =

d e s t s ( MM2dNState

i ,

QMM2dNEvent

e)

= =

0)

else i f
//

//

serv

( i . getStatus2 () 1; desocupado

0)

newy = } serv 2

11

else
}

//

ambos

ocupados + 1;

newz

i . getQSize ( )

case case case

break ;
ARRIVAL1 : newx =

break ; break ; if
}

1;

ARRIVAL2 : newy = 1;

DEPARTURE1 : ( i . getQSize ( ) newx = 1; i . getQSize ( ) != 0) {

else

newz {

1;

newx =

0;

case

break ; if
} DEPARTURE2 : ( i . getQSize ( ) newy = 1; i . getQSize ( ) != 0) {

else

newz {

1;

newy =

0;

break ;
}

return new

S t a t e s S e t <MM2dNState>(

new

MM2dNState ( newx ,

newy ,

newz ) ) ;

public @ O v e r r i d e double r a t e ( MM2dNState double r e s = 0 ; switch ( e . g e t T y p e ( ) ) { case ARRIVAL : case case case case
}

i , MM2dNState

j ,

QMM2dNEvent

e)

break ; break ; break ; break ; break ;


res res res = res =

res

lambda ;

ARRIVAL1 : lambda

alpha ;

ARRIVAL2 : lambda

(1

alpha ) ;

DEPARTURE1 : = mu1 ;

DEPARTURE2 : = mu2 ;

return

res ;

public S t r i n g d e s c r i p t i o n ( ) { return "M/M/ 2 /N SYSTEM\ n Q u e u e i n g


+ mu1 + + lambda " and " + mu2 + the + " , \ nand

@Override

System

with

two are in

servers , Poisson the

with with is

rates rate " "

"

" .\ nArrivals number

maximum

system

+ N;

12

public s t a t i c void
String stg ; BufferedReader

T h i s method j u s t t e s t s @param a Not u s e d /

the

class .

main ( S t r i n g [ ]

a)

try

new

rdr

new

BufferedReader (

I n p u t S t r e a m R e a d e r ( System . i n ) ) ;

{ System . o u t . p r i n t l n ( " E s c r i b a lambda " );

double double double double int


stg = stg = stg = stg =

stg

rdr . readLine ( ) ; lda = Double . p a r s e D o u b l e ( s t g ) ; mu1 " );

System . o u t . p r i n t l n ( " E s c r i b a rdr . readLine ( ) ; mu1 =

Double . p a r s e D o u b l e ( s t g ) ; mu2 " );

System . o u t . p r i n t l n ( " E s c r i b a rdr . readLine ( ) ; mu2 =

Double . p a r s e D o u b l e ( s t g ) ; alpha " );

System . o u t . p r i n t l n ( " E s c r i b a rdr . readLine ( ) ; alpha =

Double . p a r s e D o u b l e ( s t g ) ; en el sistema " );

S y s t e m . o u t . p r i n t l n ( "Max rdr . readLine ( ) ;

N =

Integer . parseInt ( stg ) ; theQueue =

QueueMM2dN

new

QueueMM2dN ( l d a ,

mu1 ,

mu2 ,

alpha ,

N) ;

t h e Q u e u e . showGUI ( ) ;

} } ; }

catch

theQueue . p r i n t A l l ( ) ; ( IOException e) {

//

class

end

4.2 Multiple Server Queue


In this example we generalize what we did in the previous example. exponential arrivals with exponential arrivals. There are Assume that a system has

distinct servers with service rates

1 , 2 , . . . , K . A customer that nds all servers busy joins N K (so there will be at most N customers in the system).
with probability

a single FCFS queue, with capacity A customer that nds all servers idle

will choose among the idle servers according to relative intensities

k ,

i.e., he will choose server

k =
where

k
I

kI

is the set of available servers.

4.2.1 The model


For this model we characterize each state by where

X (t) = (S (t), Q(t)),

where

S (t) = (S1 (t), . . . , SK (t)),

Sk (t) = 1

if

k -th

server is busy and 0 otherwise.

The events that can occur are arrivals

and departures. However we have to distinguish two type of arrivals. If there is no idle server the

13

arriving customer joins the queue, and we will call this a non-directed arrival. Otherwise we call it a directed arrival. We also make part of the event description the server where the arrival is directed. In order to represent this event we need a more sophisticated structure, so instead of just numbering the events we rather extend the class Event, creating an object with two integer elds (components): the type and the server. Then it is very easy to implement the functions

dest

and

rate

active,

just by querying the values of the type and server associated with the state.

4.2.2 Code
File QueueMMKdN.java

package import import import import import import import import import import
// Lets

examples . jmarkov ;

java . i o . BufferedReader ; java . i o . IOException ; java . i o . InputStreamReader ;

jmarkov . MarkovProcess ; jmarkov . SimpleMarkovProcess ; jmarkov . b a s i c . Event ; jmarkov . b a s i c . E v e n t s S e t ; jmarkov . b a s i c . P r o p e r t i e s S t a t e ; jmarkov . b a s i c . S t a t e s ; jmarkov . b a s i c . S t a t e s S e t ;

start

defining

the

State

class

This i s a p a r t i c u l a r c a s e o f p r o p e r t i e s S t a t e , whith K + p r o p e r t i e s , namely t h e s e r v e r 1 , 2 , . . . , K s t a t u s , p l u s @ a u t h o r Germn R i a o . U n i v e r s i d a d d e l o s Andes . /


QueueMMKdNState

1 the queue level .

extends

PropertiesState

private private private private


/

int K ; / / number o f s e r v e r s double sumProb = 1; / / sum o f r e l a t i v e double [ ] a l p h a ; / / r e l a t i v e f r e q u e n c y o f double [ ] b e t a ; / / p r o b a b i l i t i e s f o r t h i s


system with K

probabilities servers state

C o n s t r u c t s a s t a t e f o r an empty choosing i n t e n s i t i e s alpha . @param K Number o f s e r v e r s . /

servers ,

and

QueueMMKdNState (

int K, double [ ] this ( new int [ K ] , 0 , a l p h a ) ;

alpha )

We i d e n t i f y e a c h S t a t e w i t h s t s t u s f o t h e k s e r v e r s and t h e number i n q u e u e ( 0 , 1 , . . /

vector

that

counts

the

, N K) .

QueueMMKdNState (

int [ ] s t a t u s super ( a l p h a . l e n g t h + 1 ) ; this . K = a l p h a . l e n g t h ;

int

Qsize ,

double [ ]

alpha )

14

this . a l p h a = a l p h a ; this . b e t a = new double [ K ] ; int sum = 0 ; / / a d d s t h e number for ( int i = 0 ; i < K ; i ++) {
prop [ i ] sum + = } prop [K] } = Qsize ; = status [ i ] ; status [ i ] ;

of

busy

server

people

in

service

Computes t h e MOPs @ s e e j m a r k o v . b a s i c . S t a t e#computeMOPs ( M a r k o v P r o c e s s ) /


mp) {

public void computeMOPs ( M a r k o v P r o c e s s double sum = 0 . 0 ; for ( int i = 0 ; i < K ; i ++) {


sum + = getStatus ( i ) ; Status " + ( i + setMOP ( mp , " S e r v e r } setMOP ( mp , " Queue setMOP ( mp , " Number } Length " , in

@Override

1) ,

getStatus ( i ) ) ;

getQSize ( ) ) ; sum + getQSize ( ) ) ;

System " ,

public int g e t S t a t u s ( int return p r o p [ k ] ;


} /

Returns the s t a t u s o f @param k s e r v e r i n d e x @return S t a t u s o f the /


k)

the

kth

Server

kth

Server

public int g e t Q S i z e ( ) return p r o p [ K ] ;


} /

Returns @return /

the

size of

of

the

queue of the queue

Status

the

size

public boolean a l l B u s y ( ) boolean r e s u l t = true ; for ( int k = 0 ; r e s u l t return


} / result = result & & result ;

Determines i f a l l @ r e t u r n True , i f /

servers all

are

busy are busy . False , otherwise

servers

& &

( k < K) ;

k++) = = 1);

( getStatus (k)

public boolean a l l I d l e ( ) boolean r e s u l t = true ;

Determines i f @ r e t u r n True , /

all if

servers all

are

idle are idle . False , otherwise

servers

15

for
} /

int

k = =

0;

result & &

& &

( k < K) ;

k++) = = 0);

return

result

result

( getStatus (k)

result ;

@see /

j m a r k o v . b a s i c . S t a t e#i s C o n s i s t e n t ( )

public boolean
} /

@Override

isConsistent ()

return true ;
determines i s kept in /
the

// T O D O Complete

sum

of for

all

intensities use .

for

idle

servers .

The

result

sumProb

future

private double sum ( ) { i f ( sumProb != 1) return sumProb ; double r e s = 0 ; for ( int k = 0 ; k < K ;
res } + = (1

k++)

getStatus (k ))

alpha [ k ] ;

return

( sumProb =

res );

} /

public double p r o b ( int s e r v e r ) i f ( b e t a [ s e r v e r ] != 0 ) return b e t a [ s e r v e r ] ; return (


beta [ s e r v e r ] } = (((1

D e t e m i n e s t h e p r o b a b i l i t y o f an i d l e s e r v e r b e i n g c h o o s e n among i d l e s e r v e r s . A c u s t o m e r t h a t f i n d s more t h e n o n e s e r v e r i d l e chooses according to r e l a t i v e i n t e n s i t i e s <t e x t x t ="$ \ a l p h a _ 1 , \ a l p h a _ 2 , \ l d o t s , \ alpha_K$"> a l p h a 1 , a l p h a 2 , e t c </ t e x >. The p r o b a b i l i t y o f c h o o s i n g i d l e s e r v e r k w i l l b e g i v e n by <t e x t x t = " \ [ \ b e t a _ k = \ f r a c { \ a l p h a _ k } { \sum_{ \ e l l \ i n \ c a l I } \ a l p h a _ { \ e l l w h e r e $ \ c a l I $ i s t h e s e t o f i d l e s e r v e r s ." > a l p h a ( k ) / sum ( j , a l p h a ( j ) ) , w h e r e t h e sum i s o v e r t h e s e t o f i d l e s e r v e r s . </ t e x > @param s e r v e r s e r v e r i n d e x @ r e t u r n p r o b a b i l i t y o f an i d l e s e r v e r b e i n g c h o o s e n among i d l e s e r v e r s /
{

}} ,\]

getStatus ( server ))

alpha [ s e r v e r ] )

sum ( ) ) ) ;

R e t u r n s a l a b e l w i t h t h e f o r m a t SxxQz , @ s e e j m a r k o v . b a s i c . S t a t e#l a b e l ( ) /
String

whre

xx

is

the

list

of

busy

servers .

public for
}

@Override

label ( )
= "S" ; 0;

String (

int

stg

k =

k < K;

k++) = = 1)

{ ? "" + (k + 1) : "" ;

stg

+ =

( getStatus (k)

16

return
} /

stg

"Q"

getQSize ( ) ;

This /

method

gives

verbal

description

of

the

State .

public if

@Override String stg = description () "" ; {

String

(! allIdle ()) stg + = " Busy Servers : " ;

else for
} stg

stg (

int

+ = "No k =

one 0;

in

service " ; k++) = = 1) { ? "" + (k + 1) + " ," : "" ;

k < K;

stg

+ =

( getStatus (k)

return
} } /

+ = "

There

are

"

getQSize ( )

"

customers

waiting

in

queue . " ;

stg ;

This c l a s s d e f i n e the e v e n t s . An e v e n t h a s two c o m p o n e n t s : t y p e w h i c h c a n h a v e t h r e e v a l u e s depending whether i t r e p r e s e n t s a d i r e c t e d a r r i v a l , a non d i r e c t e d a r r i v a l o r a d e p a r t u r e , and s e r v e r , w h i c h r e p r e s e n t s the choosen s e r v e r ( i f a r r i v a l ) or the f i n i s h i n g s e r v e r . F o r non d i r e c t e d a r r i v a l s we s e t s e r v e r 1 by c o n v e n t i o n . @ a u t h o r Germn R i a o /
{

c l a s s QueueMMKdNEvent extends E v e n t f i n a l s t a t i c int NDARRIVAL = 0 ;


/ / Non directed arrival ( when all

f i n a l s t a t i c int DIRARRIVAL = 1 ; / / D i r e c t e d f i n a l s t a t i c int DEPARTURE = 2 ; int t y p e ; / / ARRIVAL o r DEPARTURE

servers

are

busy ) arrival chooses among server ( s )

int

s e r v e r = c h o s e n s e r v e r i f ARRIVAL f i n d s many s e r v e r = 1 i f no s e r v e r a v a i l a b l e s e r v e r = f i n i s h i n g s e r v e r i f DEPARTURE e v e n t /


server ;

available ,

QueueMMKdNEvent (

this . t y p e = this . s e r v e r

int

type ,

int

server )

type ; = server ;

static for
} (

E v e n t s S e t <QueueMMKdNEvent >

getAllEvents ( =

E v e n t s S e t <QueueMMKdNEvent > e S e t . add (

int int

new
i

eSet

new

int

K)

E v e n t s S e t <QueueMMKdNEvent > ( ) ;

QueueMMKdNEvent (NDARRIVAL, 0; i < K; i ++) {

1));
i ));

e S e t . add (

new new

QueueMMKdNEvent ( DIRARRIVAL ,

for

0;

< K;

i ++)

{ i ));

e S e t . add (

QueueMMKdNEvent (DEPARTURE,

17

return

eSet ;

( nonJ a v a d o c ) @ s e e j a v a . l a n g . O b j e c t#t o S t r i n g ( ) /
String stg =

public

@Override

label ( )
"" ; { :

switch case
stg

String

( type )

(NDARRIVAL) + = "Non

break ; case (DIRARRIVAL) break ; case (DEPARTURE) break ;


} stg stg

d i r e c t e d
:

arrival ";

+ = " Directed

arrival

to

server

"

( server

1);

: from server " + ( server + 1);

+ = " Departure

return

stg ;

} //

// end Lets

class start defining the State

//

Now

we

define

the

main

class

This c l a s s r e p r e s e n t s i s a system with K d i f f e r e n t e x p o n e n t i a l s e r v e r s w i t h r a t e s mu1 , mu2 , e t c , r e s p e c t i v e l y , and a r r i v a l r a t e lambda . A c u s t o m e r t h a t f i n d s more t h e n o n e s e r v e r i d l e c h o o s e s a c c o r d i n g to r e l a t i v e i n t e n s i t i e s <t e x t x t ="$ \ a l p h a _ 1 , \ a l p h a _ 2 , \ l d o t s , \ alpha_K$"> a l p h a 1 , a l p h a 2 , e t c </ t e x >. The p r o b a b i l i t y o f c h o o s i n g i d l e s e r v e r k w i l l b e g i v e n by <t e x t x t = " \ [ \ b e t a _ k = \ f r a c { \ a l p h a _ k } { \sum_{ \ e l l \ i n \ c a l w h e r e $ \ c a l I $ i s t h e s e t o f i d l e s e r v e r s ." > a l p h a ( k ) / sum ( a l p h a ( j ) ) , w h e r e t h e sum i s o v e r t h e s e t </ t e x > @ a u t h o r Germn R i a o . U n i v e r s i d a d d e l o s Andes . /
QueueMMKdN

I}

\ alpha_ {\ e l l } } , \ ]

of

idle

servers .

public c l a s s
// Eventos

extends

S i m p l e M a r k o v P r o c e s s <QueueMMKdNState , QueueMMKdNEvent >

private private private private private private private


/

double lambda ; double [ ] mu , a l p h a ; int K ; / / number o f s e r v e r s int N ; s t a t i c f i n a l int NDARRIVAL = QueueMMKdNEvent . NDARRIVAL ; s t a t i c f i n a l int DIRARRIVAL = QueueMMKdNEvent . DIRARRIVAL ; s t a t i c f i n a l int DEPARTURE = QueueMMKdNEvent .DEPARTURE;

18

public QueueMMKdN( double lambda , double [ ] mu , double [ ] super ( new QueueMMKdNState (mu . l e n g t h , a l p h a ) , this . K = mu . l e n g t h ; this . lambda = lambda ; this . mu = mu ; this . a l p h a = a l p h a ; this . N = N ;
} / QueueMMKdNEvent . g e t A l l E v e n t s (mu . l e n g t h ) ) ;

C o n s t r u c t s a M/M/Kd q u e u e w i t h a r r i v a l r a t e lambda and s e r v i c e r a t e s mu , r e l a t i v e p r o b a b i l i t i e s o f c h o o s i n g e a c h s e r v e r a l p h a @param lambda A r r i v a l r a t e @param mu Server rates @param a l p h a Relative probability o f an a r r i v i n g customer choosing @param N Max number i n t h e s y s t e m /
alpha ,

each

server .

int

N)

public QueueMMKdN ( ) { this ( 1 . 0 , new double [ ] { 2 , 3 , 4 } , new double [ ] { 2 , 3 , 4 } ,


} /

R e t u r n s an QueueMMKdN o b j e c t w i t h a r r i v a l r a t e s e r v i c e r a t e s o f 2 . 0 , 3 . 0 and 4 . 0 ; and c a p a c i t y o f 8 c u s t o m e r s i n t h e s y s t e m . Used by GUI /

1.0 ,

8);

Determines /

the

active

events .

public boolean a c t i v e ( QueueMMKdNState i , QueueMMKdNEvent e ) { boolean r e s u l t = f a l s e ; switch ( e . t y p e ) { case (NDARRIVAL) : / / NDARIIVAL o c c u r s o n l y i f s e r v e r s a r e break ; case (DIRARRIVAL)
{ result = ( i . getStatus ( e . server ) occurs if server is = = 0); / /DirARRIVAL result = ( i . allBusy () & & ( i . getQSize ( ) < N

@Override

busy

and

there

is

roon

in

K) ) ;

break ; case
{ } //

E M P T Y.

(DEPARTURE) ev . type =

= = DEPARTURE = = 1);

result

( i . getStatus ( e . server ) occurs if server is

/ /DEPARTURE } }

busy .

return

result ;

Determines /

the

possible

destination

event

( actually

one

in

this

case ) .

19

public S t a t e s <QueueMMKdNState> int [ ] s t a t u s = new int [ K ] ; for ( int k = 0 ; k < K ; k++) int Q = i . g e t Q S i z e ( ) ; switch ( e . t y p e ) { case (NDARRIVAL) : break ; case (DIRARRIVAL)
Q++; // non status [ k ] = i . getStatus (k ) ;

@Override

d e s t s ( QueueMMKdNState

i ,

QueueMMKdNEvent

e)

// copy

current

values

d i r e c t e d
: = 1;

ARRIVAL

break ; case (DEPARTURE) : i f (Q > 0 ) { / / t h e r e


status [ e . server ] Q }

status [ e . server ]

// d i r e c t e d

ARRIVAL,

picks

server .

is 1;

Queue // s e t ( keeps ) server busy

else

//

reduce

queue

status [ e . server ] }

0;

// s e t

server

idle

return new

S t a t e s S e t <QueueMMKdNState>(

new

QueueMMKdNState ( s t a t u s ,

Q,

alpha ) ) ;

The r a t e i s lambda , o r mu f o r non d i r e c t e d a r r i v a l and f o r d e p a r t u r e . F o r d i r e c t e d a r r i v a l r a t e i d lambda 8 p r o b ( s e r v e r i s c h o o s e n ) @ s e e j m a r k o v . S i m p l e M a r k o v P r o c e s s#r a t e ( j m a r k o v . S t a t e , j m a r k o v . S t a t e , j m a r k o v . E v e n t ) /


i , QueueMMKdNState j , QueueMMKdNEvent e) {

public double r a t e ( QueueMMKdNState double r e s u l t = 0 ; switch case


( e . type ) { : (DEPARTURE)

@Override

break ; case (NDARRIVAL)


result =

result

= mu [ e . s e r v e r ] ;

break ; / / non d i r e c t e d case (DIRARRIVAL) :


result } =

lambda ;

arrival

i . prob ( e . s e r v e r )

lambda ;

return

result ;

public s t a t i c void new try {


BufferedReader

Main Method . T h i s a s k s t h e and t e s t s t h e p r o g r a m . @param a Not u s e d /


rdr =

user

for

parameters

main ( S t r i n g [ ]

a)

BufferedReader (

new

I n p u t S t r e a m R e a d e r ( System . i n ) ) ;

double

System . o u t . p r i n t l n ( " I n p u t lda =

Rate :

" );

Double . p a r s e D o u b l e ( r d r . r e a d L i n e ( ) ) ; Servers : " );

S y s t e m . o u t . p r i n t l n ( "Num

20

int K = I n t e g e r . p a r s e I n t ( r d r . r e a d L i n e ( ) ) ; double mu [ ] = new double [ K ] ; double a l p h a [ ] = new double [ K ] ; for ( int k = 0 ; k < K ; k++) {
System . o u t . p r i n t l n ( " S e r v i c e mu [ k ] } = rate , server " + (k + 1) + " : " ); Double . p a r s e D o u b l e ( r d r . r e a d L i n e ( ) ) ;

for

int

k =

0;

k < K;

k++)

System . o u t . p r i n t l n ( " Choosing alpha [ k ] } S y s t e m . o u t . p r i n t l n ( "Max = intensity , server " + (k + 1) + " : " );

Double . p a r s e D o u b l e ( r d r . r e a d L i n e ( ) ) ;

int

in

system

" );

N =

Integer . parseInt ( rdr . readLine ( ) ) ; theModel =

QueueMMKdN

new

QueueMMKdN( l d a ,

mu ,

alpha ,

N) ;

t h e M o d e l . showGUI ( ) ; // theModel . s e t D e b u g L e v e l ( 2 ) ;

} }; }

catch

theModel . p r i n t A l l ( ) ; ( IOException e) {

@see /

j m a r k o v . S i m p l e M a r k o v P r o c e s s#d e s c r i p t i o n ( )

public
stg stg

@Override String stg = description () {

String

"M/M/ k /N SYSTEM\ n \ n " ; server Rate = " queue + with " + + " ,

+ = " Multiple + = " Arrival stg ;

this . K
Max

"

different in system

s e r v e r s \n" ; " + N;

return
} } // c l a s s

lambda

number

end

4.3 Drive Thru


4.3.1 Code
File DriveThru.java

package import import import import import import import import import import import

examples . jmarkov ;

static static static static static static static static

e x a m p l e s . j m a r k o v . D r i v e T h r u E v e n t . Type . ARRIVAL ; e x a m p l e s . j m a r k o v . D r i v e T h r u E v e n t . Type . MIC_COMPLETION ; e x a m p l e s . j m a r k o v . D r i v e T h r u E v e n t . Type . SERVICE_COMPLETION ; e x a m p l e s . j m a r k o v . D r i v e T h r u S t a t e . C u s t S t a t u s .B L O C K E D _ D O N E; e x a m p l e s . j m a r k o v . D r i v e T h r u S t a t e . C u s t S t a t u s . COOKING ; e x a m p l e s . j m a r k o v . D r i v e T h r u S t a t e . C u s t S t a t u s .E M P T Y; e x a m p l e s . j m a r k o v . D r i v e T h r u S t a t e . C u s t S t a t u s . ORDERING ; e x a m p l e s . j m a r k o v . D r i v e T h r u S t a t e . C u s t S t a t u s . WAIT_MIC ;

java . io . PrintWriter ;

jmarkov . MarkovProcess ; jmarkov . SimpleMarkovProcess ;

21

import import import import import import import


/

jmarkov . b a s i c . Event ; jmarkov . b a s i c . E v e n t s S e t ; jmarkov . b a s i c . S t a t e ; jmarkov . b a s i c . S t a t e s ; jmarkov . b a s i c . S t a t e s S e t ; jmarkov . b a s i c . e x c e p t i o n s . N ot U ni ch ai nE xc e pt io n ; examples . jmarkov . D r i v e T h r u S t a t e . C u s t S t a t u s ;

E s t e p r o g r a m a d e s c r i b e un @ a u t h o r M a r g a r i t a Arana y Mod : Germn R i a o ( 2 0 0 4 ) @version 1.0 a /

DriveThru .

Gloria

Daz .

Universidad

de

los

Andes .

E s t e e s un c a s o p a r t i c u l a r d e P r o p e r t i e s S t a t e . Llamamos N l a m i c r f o n o . L a s p r i m e r a s N1 p o s i c i o n e s r e p r e s e n t a n e l s t a t u s c o l a , l a p o s i c i o n N e l s t a t u s d e l m i c r o f o n o , N+1 c a n t i d a d e n servidores disponibles . /


DriveThruState

posicion de la y

del

primera N+2

cola

class
// //

extends

State

private private

int

micPos ; micStatus ;

private int numQ ; private int a v l S e r v ; private C u s t S t a t u s [ ]


This /
/ enumeration

CustStatus

prop

null ;
differents status for a customer .

shows

the

public
/

enum

CustStatus vacio .

Sitio

/ /
micrfono pero no hay servidores para que me atiendan .

EMPTY, En servicio .

ORDERING, / Estoy en el

WAIT_MIC, / Me estn haciendo la orden .

/
estoy bloqueado .

COOKING, / Ya esta listo el pedido pero

B L O C K E D _ D O N E; }

Builds @param @param /

State

represinting

an

empty

system

micPos serv

DriveThruState (

this ( new for ( int

int
= 0;

micPos ,

int

serv )

{ 0, { serv ) ;

C u s t S t a t u s [ micPos ] , i i <

EMPTY,

prop . l e n g t h ;

i ++)

22

prop [ i ] } }

= E M P T Y;

C o n s t r u y e un n u e v o e s t a d o D r i v e T h r u . @param v e c Estados desde l a ventana hasta el @param m i c Estado d e l micrfono . @param numQ Cantidad de p e r s o n a s en l a cola . @param a v S e r v s Servidores disponibles /

micrfono

( sin

incluirlo ).

DriveThruState ( CustStatus [ ]

int
=

statusVec ,

CustStatus

micStatus ,

int

numQ,

prop

int

new

avServs )

{ + 1];

CustStatus [ statusVec . length = statusVec . length ; 0, prop , 0,

micPos

System . a r r a y c o p y ( s t a t u s V e c , prop [ micPos ]

micPos ) ;

this . numQ = numQ ; this . a v l S e r v = a v S e r v s ;

micStatus ;

Compute /

all

the

MOPs

for

this

state

public void computeMOPs ( M a r k o v P r o c e s s int s e r v E t a p a 1 = 0 ; int s e r v E t a p a 2 = 0 ; int b l o c k e d D o n e = 0 ; int b l o c k e d B e f o r e = 0 ; int t o t a l = 0 ; for ( C u s t S t a t u s s : p r o p ) {


servEtapa1 servEtapa2 + = + = (s (s = = ORDERING) = = COOKING) ? blockedDone + = (s

@Override

mp)

? 1

1 :

0; 0; ? 1 1 : : 0; 0;

= = B L O C K E D _ D O N E) (s = = WAIT_MIC) ? 1 : 0; ?

blockedBefore total } setMOP ( mp , setMOP ( mp , setMOP ( mp , setMOP ( mp , setMOP ( mp , setMOP ( mp , setMOP ( mp , setMOP ( mp , + setMOP ( mp , } + = (s

+ =

!= E M P T Y)

"Tamano " Serv " Serv " Serv

Cola " ,

getQLength ( ) ) ; Microfono " , servEtapa1 ) ; servEtapa2 ) ; + servEtapa2 ) ; ordenar " , lista " , + blockedBefore ) ; blockedDone ) ; blockedDone ) ; + blockedDone

Ocupados Ocupados Ocupados

Cocinando " , " ,

servEtapa1 antes con

" Clientes " Clientes " Clientes " Total

Bloqueados Bloqueados

de

orden

Bloqueados " , en

blockedBefore

clientes

Espera " ,

blockedBefore

getQLength ( ) ) ; " Total Clientes " , total + getQLength ( ) ) ;

23

public int return


} /

Obtiene @return /

el

nmero

de

personas

en

la

cola

Nmero

de

personas

en

la

cola .

getQLength ( ) numQ ;

public C u s t S t a t u s g e t S t a t u s ( int return p r o p [ i ] ;


} /

O b t i e n e e l e s t a d o de @param i posicion @return Estado en l a /

la

posicin

i .

posicin

i .

i )

public C u s t S t a t u s [ ] g e t S t a t u s ( ) { int m i c P o s = g e t M i c P o s ( ) ; CustStatus [ ] s t a t u s = new C u s t S t a t u s [ m i c P o s ] ; return


} / System . a r r a y c o p y ( prop , status ; 0, status , 0, micPos ) ;

Obtiene @return /

el

vector

de

estado

de

los

clientes

Estado

en

la

posicin

numMic

public C u s t S t a t u s g e t M i c S t a t u s ( ) int n = p r o p . l e n g t h 1 ; return p r o p [ n ] ;


} /

Obtiene @return /

el

estado

de

la

ventana .

Estado

del

cliente

en

el

micrfono

public int return


} /

Return t h e mic p o s i t i o n . @ r e t u r n mic p o s i t i o n i n d e x /


getMicPos ( ) prop . l e n g t h {

1;

public

Obtiene @return /

el

estado

de

la

ventana .

Estado

de

la

ventana .

CustStatus

getVentana ( )

24

return
} /

prop [ 0 ] ;

public int return


} /

Obtiene @return /

el

nmero

de

servidores

disponibles

Estado

de

la

ventana .

getAvlServs () avlServ ;

@see /

j m a r k o v . b a s i c . S t a t e#i s C o n s i s t e n t ( )

public boolean
}

@Override

isConsistent ()

return true ;
@Override String stg

// T O D O Complete

public

label ( )
= "" ; s

for

String

switch ( s ) { case EMPTY: case case case case


}

( CustStatus

prop )

break ; break ; break ; break ; break ;


stg stg stg stg

stg

+ = "0" ;

ORDERING : + = "m" ;

WAIT_MIC : + = "w" ;

COOKING : + = "c" ;

B L O C K E D _ D O N E: + = "b" ;

return
//

stg

+ stg

"Q" +

+ numQ ; "Q" + prop [ micPos + 1] + "S" + prop [ micPos + 2];

return

String

switch ( s t a t ) { case EMPTY: return " empty " ; case ORDERING : return " o r d e r i n g , " ; case WAIT_MIC : return " w a i t i n g " ; case COOKING : return " c o o k i n g " ;

statusDesc ( CustStatus

stat )

25

default : / / DONE return " b l o c k e d " ;


} }

Describes the State @ s e e j m a r k o v . b a s i c . S t a t e#d e s c r i p t i o n ( ) /


String stg description () = "" ; {

public

@Override

int for
} stg stg stg

String N = = (

getMicPos ( ) ; CustStatus : 0; i < N; (" ; {

int

" Queue i =

i ++)

stg stg

+ = + =

statusDesc ( getStatus ( i ) ) ; ( i < N

1)

" ,

"

"" ;

+ = " ). + = ".

Mic Queue

status : Size : "

"

statusDesc ( getMicStatus ( ) ) ;

return
} /

getQLength ( ) ;

stg ;

@see /

j m a r k o v . b a s i c . S t a t e#compareTo ( j m a r k o v . b a s i c . S t a t e )

public int compareTo ( S t a t e j ) { i f ( ! ( j instanceof D r i v e T h r u S t a t e ) ) throw new I l l e g a l A r g u m e n t E x c e p t i o n ( " C o m p a r i n g int for


DriveThruState micPos ( = u = ( DriveThruState ) j ; getMicPos ( ) ;

@Override

wrong

types ! " ) ;

int k = 0 ; k <= m i c P o s ; k++) { i f ( getStatus (k ) . ordinal () > u . getStatus (k ) . ordinal ()) return + 1 ; i f ( getStatus (k ) . ordinal () < u . getStatus (k ) . ordinal ()) return 1;
> u . getQLength ( ) ) +1; < u . getQLength ( ) )

if if if if

( getQLength ( )

return

( getQLength ( )

return 1; return
+1;

( getAvlServs ()

>

u . getAvlServs ( ) )

return 1; return 0 ;
} }

( getAvlServs ()

<

u . getAvlServs ( ) )

class

Esta c l a s e implementa SimpleMarkovProcess . /


DriveThruEvent

eventos

en

un

Drive

Thru .

Extendiende

la

clase

extends

jmarkov . b a s i c . Event

26

public s t a t i c
/

Event

types .

/
Type the { system . to

enum

Arrivale

/ /
who ordered .

ARRIVAL, / Car at mic finishes service .

MIC_COMPLETION, / Service completion for somebody

SERVICE_COMPLETION ; }

private Type t y p e ; / / private int p o s i t i o n ;


/

event //

type del cliente que termina

Posicion

public
}

C r e a t e s an ARRIVAL @param t y p e /

or

MIC_COMPLETION

event .

D r i v e T h r u E v e n t ( Type ( type = = = ARRIVAL type ;

type ) ||

{ = = MIC_COMPLETION ) ;

this . t y p e
/

assert

type

public D r i v e T h r u E v e n t ( int p o s i t i o n ) this . t y p e = SERVICE_COMPLETION ; this . p o s i t i o n = p o s i t i o n ;


} /

C r e a t e s a S e r v i c e Completion @param p o s i t i o n P o s t i o n where t h e /

event

at

he

given

position .

event

occurs

based

).

public int
assert }

@return /

position

where

this

event

occurs .

( valid

only

if

type

= =

SERVICE_COMPLETION ) .

getPos ( ) ( type

return
/

= = SERVICE_COMPLETION ) ;

position ;

public Type g e t T y p e ( ) return t y p e ;


} /

@return /

event

type

public s t a t i c

@param m i c P o s @return A s e t /

with

all

the

events

in

the

system .

E v e n t s S e t <D r i v e T h r u E v e n t >

E v e n t s S e t <D r i v e T h r u E v e n t > e S e t . add (

new

eSet

new

getAllEvents (

int

micPos )

E v e n t s S e t <D r i v e T h r u E v e n t > ( ) ;

D r i v e T h r u E v e n t (ARRIVAL ) ) ;

27

for
}

e S e t . add ( (

int

new
i =

D r i v e T h r u E v e n t (MIC_COMPLETION ) ) ;

return
@Override

e S e t . add ( eSet ;

new

0;

<=

micPos ;

i ++)

DriveThruEvent ( i ) ) ;

public

String stg

label ( )
= "" ; {

switch ( t y p e ) case ARRIVAL : case break ;


stg = stg =

String

" Arrival " ;

MIC_COMPLETION : " MicEnd " ;

break ; default :
stg } =

" SrvEnd ( "

position

")" ;

return

stg ;

Esta c l a s e implementa SimpleMarkovProcess . /


DriveThru

un

Drive

Thru .

Extendiende

la

clase

public c l a s s double double double int M; int S ; int N ;


/

extends
DriveThruEvent> { Tasa de de de arribo

S i m p l e M a r k o v P r o c e s s <D r i v e T h r u S t a t e ,

lambda ; mu1 ; mu2 ; // // // // //

//

Tasa Tasa

servicio servidor de

servidor

Nmero Nmero Nmero

mximo de de

entidades

en

el

sistema

servidores puestos entre la ventana y el micrfono

public D r i v e T h r u ( double lambda , double mu1 , double mu2 , int M, int S , int super ( ( new D r i v e T h r u S t a t e (N , S ) ) , D r i v e T h r u E v e n t . g e t A l l E v e n t s (N ) ) ;
28

C o n s t r u c t o r d e un D r i v e T h r u . @param lambda Tasa de a r r i b o s @param mu1 Tasa de servicios del micrfono @param mu2 Tasa de servicios de l a v e n t a n a @param M Nmero mximo d e e n t i d a d e s e n e l sistema @param S Nmero d e s e r v i d o r e s @param N Nmero d e p u e s t o s entre l a ventana y e l micrfono /

N)

this . lambda = lambda ; this . mu1 = mu1 ; this . mu2 = mu2 ; this .M = M; this . S = S ; this . N = N ;
}

public D r i v e T h r u ( ) { this ( 8 0 . 0 , 1 2 . 0 ,
} /

Default /

constructor

for

GUI .

30.0 ,

4,

2,

1);

Determina cuando l o s e v e n t o s e s t n a c t i v o s p a r a @ s e e S i m p l e M a r k o v P r o c e s s#a c t i v e ( S t a t e , E v e n t ) /

cada

estado

public boolean a c t i v e ( D r i v e T h r u S t a t e boolean r e s u l t = f a l s e ; switch ( e v . g e t T y p e ( ) ) { case ARRIVAL :


// un carro = puede llegar si

@Override

s ,

DriveThruEvent

ev )

hay

espacio

en

cola

case

break ;
// // se el

result

( s . getQLength ( )

< M

1);

MIC_COMPLETION : puede pedido = ( s . getMicStatus () = = ORDERING ) ; terminar de tomar la orden si una persona esta haciendo

break ; default :
// // se

result

puede

terminar

una

orden

si

la

persona

correspondiente

la

esta

if

esperando ( ev . g e t Po s ( ) = = N) { = = COOKING ) ;

else

result {

( s . getMicStatus ()

result } }

( s . g e t S t a t u s ( ev . g et P o s ( ) )

= = COOKING ) ;

return

result ;

La t a s a e s lambda s i hay un a r r i b o , l a t a s a e s mu1 s i s e r v i c i o t i p o 1 y mu2 s i s e t e r m i n a un s e r v i c i o t i p o @ s e e S i m p l e M a r k o v P r o c e s s#r a t e ( S t a t e , i n t ) /


i , DriveThruState j ,

se 2.

termina

un

public double r a t e ( D r i v e T h r u S t a t e switch ( e . g e t T y p e ( ) ) { case ARRIVAL :

@Override

DriveThruEvent

e)

29

case

return

lambda ;

return default : return

MIC_COMPLETION : mu1 ;

mu2 ;

} }

Determina e l e s t a d o d e s t i n o cuado @ s e e S i m p l e M a r k o v P r o c e s s#d e s t s ( S , /

un

evento

ocurre .

E)

public S t a t e s <D r i v e T h r u S t a t e > d e s t s ( D r i v e T h r u S t a t e int numServ = i . g e t A v l S e r v s ( ) ;


CustStatus [ ] CustStatus status = i . getStatus ( ) ;

@Override

i ,

DriveThruEvent

e)

int n e w Q s i z e = i . g e t Q L e n g t h ( ) ; int numGone = 0 ; boolean micMoves = f a l s e ; int k ; / / u t i l i t y c o u n t e r switch ( e . g e t T y p e ( ) ) { case ARRIVAL : i f ( i . getMicStatus ()
// Hay espacio

newMic =

i . getMicStatus ( ) ;

= = E M P T Y & & numServ > el microfono y hay

0)

en

servidores

newMic = ORDERING ;

else i f
//

numServ = numServ

el

1; = = E M P T Y & & numServ = = y no hay 0) {

( i . getMicStatus () espacio en

Hay

microfono

servidores

else i f
//

newMic = WAIT_MIC ; ( i . getQLength ( ) ocupado , < M

en

1)

Micrfono =

espacio 1;

cola .

newQsize

i . getQLength ( )

break ; case
MIC_COMPLETION : newMic = COOKING ;

for if

(k = ;

0;

( ( k < N)

& &

( status [ k ]

!= E M P T Y) ) ;

k++)

//

k (k

es !=

la N)

1a {

posicion // Si hay

disponible sitio lo movemos

status [ k ]

= COOKING ;

newMic = E M P T Y; micMoves =

true ;

break ; default : int p i f (p


// 2 nd SERVICE_COMPLETION 1; // se libera un servidor numServ = numServ + = > e . getPos ( ) ; 0 & & p < N) si esta listo { el pedido de una persona en el medio o mic

//

status [ p ]

= B L O C K E D _ D O N E;

30

else i f else
{ //

(p = = N)

//

Esta

listo

el

mic

newMic = B L O C K E D _ D O N E; // ( p ==0). Esta listo el pedido de la persona en la

ventana = E M P T Y; desocupamos al servidor

status [ 0 ] //

int for if

tentativamente pos1 , pos2 ; el

//

encontramos (k = ; 1;

primer & &

cliente status [ k ]

no

bloqueado : k++)

( ( k < N)

= = B L O C K E D _ D O N E) ;

numGone = k ; (k != N) {

// //

el El

numero primer

que

salen es el mic

NB NO

pos1 //

= k; cliente en // posicion el de pos1 es va el { a quedar en en la la ventana

El

pos2

for

= N (k =

1;

pos2

ultimo

cola

pos1 ;

k <=

pos2 ; =

k++)

status [ k // } } los

numGone ] todos

status [ k ] ;

movemos

for if

(k = N

numGone ; = E M P T Y;

k < N; // el

k++) resto

{ esta vaco

status [ k ] }

( newMic = = COOKING) // movemos el del

{ microfono al final de la cola :

s t a t u s [N

numGone ]

= newMic ;

newMic = E M P T Y;

else i f
//

micMoves

true ;
{ se va

( newMic = = B L O C K E D _ D O N E) del microfone

El

newMic = E M P T Y; micMoves } =

true ;

break ;
} // end switch

if
}

( newMic = = WAIT_MIC & & numServ > newMic = ORDERING ; numServ

0)

;
{ > 0 & & numServ > 0) {

if

( micMoves )

if

( i . getQLength ( )

newMic = ORDERING ; numServ = numServ

1;

else i f

newQsize

i . getQLength ( ) >

1; 0) {

( i . getQLength ( )

0 & & numServ = =

newMic = WAIT_MIC ; newQsize } } S t a t e s S e t <D r i v e T h r u S t a t e > = i . getQLength ( )

1;

return
} // end @Override

s e t . add (

new

set

new

S t a t e s S e t <D r i v e T h r u S t a t e > ( ) ; newQsize , numServ ) ) ;

DriveThruState ( status ,

newMic ,

set ;

dests

31

public S t r i n g d e s c r i p t i o n ( ) { return "SISTEMA DRIVE THRU.


+ " \ nTasa en el Mic + mu2 + + S + } "\ nPosicin en el " \ nCap

"

" \ nTasa "

de

Entrada " \ nTasa

= de

"

lambda 2 = " = "

= del

+ mu1 + = " "

sevicio

mic =

+ N +

"\ nServi dores

sistema

+ M;

Print /

all

waiting

times

associated

with

each M O P

public int printMOPs ( P r i n t W r i t e r o u t , int int namesWidth = super . printMOPs ( o u t , double try {
// this rate work for all MOPs ldaEff ;

@Override

width , width ,

int

decimals )

decimals ) ;

ldaEff

g e t E v e n t R a t e (ARRIVAL . o r d i n a l ( ) ) ; names = getMOPNames ( ) ;

double w a i t T i m e ; int N = names . l e n g t h ;


namesWidth + =

String [ ]

for

int

20; 0; i 60 < N; i ++) { / ldaEff ;

waitTime String

getMOPsAvg ( names [ i ] ) time for " +

name =

" Waiting

o u t . p r i n t l n ( pad ( name , +

namesWidth , width ,

false )

names [ i ] ;

pad ( w a i t T i m e ,

decimals )

"

minutes " ) ;

catch

( NotUnichainException

e)

out . p r i n t l n ( e ) ; }

return

namesWidth ;

public s t a t i c void
// as in DriveThru // DriveThru

Main method . @param a Not /

used .

main ( S t r i n g [ ]

a)

handout : theDT =

new

DriveThru ( 8 0 . 0 ,

12.0 ,

30.0 ,

4,

2, 4,

1); 2, 2);

theDT = new

DriveThru ( 8 0 . 0 ,

120.0 ,

30.0 ,

theDT . s e t D e b u g L e v e l ( 5 ) ;

theDT . showGUI ( ) ; theDT . p r i n t A l l ( ) ; theDT . printMOPs ( ) ; }

//

class

end

4.3.2 Results
Output for Drive Thru

32

SISTEMA DRIVE T HR U. Tasa Tasa Tasa de en de Entrada el Mic 2 = = = mic = sistema = 4 14 80.0 120.0 30.0 = 5

sevicio del

P o s i c i {\ ' o }n Servidores Cap en el

System

has

498

States .

MEASURES OF P E R F O R M A N C E

N A M E Tamano Serv Serv Serv Cola Microfono Cocinando

M E A N 4.503 0.550 2.199 2.749 antes con de ordenar lista 0.112 1.540 1.652 6.155 8.903

SDEV 2.693 0.498 1.165 1.088 0.316 1.646 1.604 3.487 3.396

Ocupados Ocupados Ocupados

Clientes Clientes Clientes Total Total

Bloqueados Bloqueados Bloqueados en

orden

clientes Clientes

Espera

EVENTS O C C U R A N C E RATES N A M E Arrival MicEnd SrvEnd ( 0 ) SrvEnd ( 1 ) SrvEnd ( 2 ) SrvEnd ( 3 ) SrvEnd ( 4 ) SrvEnd ( 5 ) M E A N RATE 65.965 65.965 28.019 9.927 9.446 8.333 6.114 4.126

Tiempo Tiempo Tiempo Tiempo Tiempo Tiempo Tiempo Tiempo Tiempo

de de de de de de de de de

espera espera espera espera espera espera espera espera espera

para para para para para para para para para

Tamano Serv Serv Serv

Cola :

4.096

minutos : 2 0.5 minutos

Ocupados Ocupados Ocupados

Microfono Cocinando : : 2.5

minutos

minutos antes con de ordenar : lista : 0.102 1.4 minutos

Clientes Clientes Clientes Total Total

Bloqueados Bloqueados Bloqueados : en :

orden

minutos

1.503

minutos 5.598 minutos

clientes Clientes

Espera : 8.098

minutos

Modeling Quasi-Birth and Death Processes

In this section we give a brief description of Quasi-Birth and Death Processes (QBD), and explain how they can be modeled using jMarkov. QBD are Markov Processes with an innite space state, but with a very specic repetitive structure that makes them quite tractable.

33

5.1 Quasi-Birth and Death Processes


{X (t) : t 0} with a two dimensional state space S = {(n, i) : n 0, 0 i m}. The rst coordinate n is called the level of the process and the second coordinate i is called the phase. We assume that the number of phases m is nite. In applications, the level
Consider a Markov process usually represents the number of items in the system, whereas the phase might represent dierent stages of a service process. We will assume that, in one step transition, this process can go only to the states in the same level or to adjacent levels. This characteristic is analogous to a Birth and Death Process, where the only allowed transitions are to the two adjacent states (see, e.g [4]). Transitions can be from state

(n, i)

to state

(n , i )

only if

n = n, n = n 1

or

independent of the level

n.

Therefore, the generator matrix,

B00 B01 B10 A1 A0 Q= A2 A1 A0


.. . .. .

n = n + 1, and, for n 1 the Q, has the following ,


.

transition rate is structure

..

where, as usual, the rows add up to 0. An innite Markov Process with the conditions described above is called a Quasi-Birth and Death Process (QBD). In general, the level zero might have a number of phases has size

m0 = m. (m0 m)

We will call these rst and

states the boundary states, and all other states will be called typical states. Note that matrix

m0 B00

m0 m0 ,

whereas

B01

and

B10

are matrices of sizes

(m m0 ),

respectively.

Assume that the QBD is an ergodic Markov Chain. As a result, there is a steady state distribution

that is the unique solution

to the system

Q = 0, 1 = 1.

Divide this

vector by levels,

analogously to the way

was divided, as

= [ 0 , 1 , . . .].
Then, it can be shown that a solution exist that satisfy

n+1 = n R,
where

n > 1, R
is the solution to the equation

is a constant square matrix of order

[6]. This

A0 + RA1 + R2 A2 = 0.
There are various algorithms that can be used to compute the matrix start with any initial guess

R.

For example, you can

R0

and obtain a series of

Rk

through iterations of the form

1 Rk+1 = (A0 + R2 k A2 )A1 .


This process is shown to converge (and

A1

does have an inverse).

More elaborated algorithms

are presented in Latouche and Ramaswami [5]. Once

has been determined then

and

are

determined by solving the following linear system of equations

0 1

B00 B01 = 0 0 B10 A1 + RA2

0 1 + 1 (I R)1 1 = 1.

34

5.2 Measures of performance for QBDs


We consider two types of measures of performance that can be dened in a QBD model. The rst type can be seen as a reward for level

ri

received whenever the system is in phase i, independent of the level,

n 1.

The long-run value for such a measure of performance is computed according to

n r = 1 (I R)1 r,
n=1
where

is an

m-size

column vector with components

ri .

The second type of reward has the form

nri ,

whenever the system is in phase

of level

n.

Its long-run value is

n n r = 1 R(I R)2 r.
n=1

5.3 Modeling QBD with jQBD


Modeling QBD with jMarkov is similar to modeling a Markov Processes. Again, the user has to code the states, the events, and then dene the dynamics of the system through

rate.

active, dests, and

The main dierence is that special care needs to be taken when dening the destination states

for the typical states. Rather than dening a new level for the destination state, the user should give a new relative level, which can be -1, 0, or +1. This is accomplished by using two dierent classes to dene states. The current state of the system is a GeomState, but the destination states are GeomRelState. The process itself must extend the class GeomProcess, which in turn is an extension of MarkovProcess. The building algorithm uses the information stored about the dynamics of the process to explore the graph and build only the rst three levels of the system. extract matrices From this, it is straightforward to

B00 , B01 , B10 , A0 , A1 ,

and

A2 .

Once these matrices are obtained, the stability

condition is checked. If the system is found to be stable, then the matrices passed to the solver, which takes care of computing the matrix vectors

A0 , A1 ,

and

A2

are

R and the steady state probabilities

0 and 1 , using the formulas described above.

The implemented solver (MtjLogRedSolver)

uses the logarithmic reduction algorithm [5]. This class uses MTJ for matrices manipulations. There are also mechanisms to dene both types of measures of performance mentioned above, and jQBD can compute the long run average value for all of them.

5.4 An Example
To illustrate the modeling process with jQBD, we will show the previous steps with a simple example. Consider a innite queue with a station that has a single hiper-exponential server with phases, with probability

to reach the service phase

and with service rate

at phase

n service i, where

0 i n. . We will

The station is fed from an external source according to a Poisson processes with rate use this model as an illustrative example of a QBD process, and will show how each

of the previous steps is performed for this example. Of course all measures of performnce for this system can be readilly obtained in closed form since it is a particular case of an distribution, so the hyper-geometric will be a particular case.

M/G/1,

but we

chose this example bacause of its simplicity. The code below actually models any general phase-type

States:

Because of the memoryless property, the state of the system is fully characterized

by an integer valued vector system and

x = (x1 , x2 ), where x1 0 represents the number of items in the 0 x2 n represents the current phase of the service process.Note that, knowing

this, we can know how many items are in service and how many are queuing. It is important

35

to highlight that the computational representation uses only the phase of the system (x2 ) because the level (x1 )is manged internally by the framework.

Events:

An event occurs whenever an item arrives to the system or nishes processing at

a particular service phase

0 i n.

Therefore, we will dene the set of possible events as

E = {a, c1 , c2 , . . . , cn }, Markov Process:


three methods:

where the event

represents an arrival to the system and an event

ci

represents the completion of a service in phase We elected to implement

i.

GeomProcess, which implied coding the following


a
is always active,

 active (i,e):
and the events

Since the queue is an innite QBD process the event

ci , 0 i n

are active if there is an item at workstation on service phase

i.

The code to achieve this can be seen in Figure 6. When the event

 dests (i,e,j):

occurs there is always an increment on the system

level, but you need to consider if the server is idle or busy. When the server is idle the new costumer could start in any of the anyone of the rst level busy on service phase phase

service phases, then the system could reach

states with probability

i .

On the other hand, if the server is

i,

the system will reach the next level state with the same service

i. ci ,
no matter which phase type,

On the other hand, when the server nishes one service

the level of the system is reduced by one, but you need to consider if the system is in level 1 or if it is in level 2 or above. When the level is 1, the system reach the unique state (0, 0) where there are no costumer in the system and the server is idle. the 7. On the other hand, if the system level is equal or greater than 2, the system could reach any of

states in the level below with probability

i . a

The Java code can be seen in Figure

 rate (i,e):
MOPs:

The rate of occurrence of event

is given simply by

and the rate of

occurrence of an event

ci

is given by

i .

In Figure 8 you can see the corresponding code.

Using the MOPS types dened in jQBD component, we will illustrate its use calcu-

lating the expected WIP on the system.

File HiperExQueue.java

switch ( e . t y p e ) { case ARRIVAL : r e s u l t = true ; break ; case FINISH_SERVICE : break ;


} result = ( i . getSrvPhase ( ) = = e . getCurPH ( ) ) ;

return

result ;

( non

J a v a d o c )
Figure 6:

Active

method of class HiperExQueue.java

36

File HiperExQueue.java
=

new

S t a t e s S e t <G e o m R e l S t a t e<H i p e r E x Q u e u e S t a t e > > () ;

int int

n e w Ph a s e rLevel =

= 0;

i . getSrvPhase ( ) ;

switch ( e . t y p e ) case ARRIVAL :


rLevel

if

+1; = = 0) destStates );

( absLevel

else

addDestsFinishServer ( rLevel ,

d e s t S t a t e s . add (

case

break ;
rLevel

new

new

G e o m R e l S t a t e<H i p e r E x Q u e u e S t a t e >( rLevel ) ) ;

H i p e r E x Q u e u e S t a t e ( n e w P h as e ) ,

FINISH_SERVICE :

if

1;
= = 1)

( absLevel

d e s t S t a t e s . add (

else break ;
}

new

new

G e o m R e l S t a t e<H i p e r E x Q u e u e S t a t e >(

HiperExQueueState ( 0 ) ) ) ;

addDestsFinishServer ( rLevel ,

destStates );

return
end of

destStates . toStateArray ( ) ; dest

} //

T h i s method c a l c u l a t e s occurs the event e .


Figure 7:

the

rate

of

transition

from

to

when

dests

method of class HiperExQueue.java

Finally, the output obtained after running the model can be seen in the Graphical User Interface (GUI) in Figure 9. There is no need to use the GUI, but it is helpful to do so during the rst stages of development, to make sure that all transitions are being generated as expected. All the measures of performance dened can be extracted by convenience methods dened in the API or a report printed to standard output. Such a report can be seen in Figure 10.

Advanced Features

6.1 6.2 6.3 6.4


7

Using the Solvers Using the Transitions scheme Computing MOPs on the y to save memory extending jMarkov
Further Development

This project is currently under development, and therefore we appreciate all the feedback we can receive.

37

File HiperExQueue.java

case

i f ( i L e v e l == 0 ) { int n e w Ph a s e = double a l p h a [ ]
rate } = lambda

ARRIVAL :

j . getSrvPhase ( ) ; = servDist . getVectorArray ( ) ; a l p h a [ n e w P ha s e

1];

else {
rate = lambda ;

case

break ; if
FINISH_SERVICE : ( iLevel

int n e w Ph a s e = double a l p h a [ ]
rate =

>

1){

j . getSrvPhase ( ) ; = servDist . getVectorArray ( ) ;

a [ e . getCurPH ( )

1]

a l p h a [ n e w P ha s e

1];

else {
rate = a [ e . getCurPH ( )

1];

break ;
}

return
end of

rate ; rate

} // /

( nonJ a v a d o c ) @ s e e j m a r k o v . S i m p l e M a r k o v P r o c e s s#d e s c r i p t i o n ( ) /
String description () {

public

@Override

Figure 8:

rate

method of class HiperExQueue.java

References
[1] G. Ciardo. Tools for formulating Markov models. In W. K. Grassman, editor, Computational
Probability. Kluwer's International Series in Operations Research and Management Science,

Massachusetts, USA, 2000. [2] B. Heimsund. Matrix Toolkits for Java (MTJ). Webpage:

http://rs.cipr.uib.no/mtj/,

December 2005. Last checked on 05-Dec-2005. [3] J. Hicklin, C. Moler, P. Webb, R. F. Boisvert, B. Miller, R. Pozo, and K. Remington. JAMA: A java matrix package. Webpage: http://math.nist.gov/javanumerics/jama/, July 2005. MathWorks and the National Institute of Standards and Technology (NIST). [4] V. Kulkarni. Modeling and analysis of stochastic systems. Chapman & Hall., 1995. [5] G. Latouche and V. Ramaswami. Introduction to matrix analytic methods in stochastic modeling. Society for Industrial and Applied Mathematics (SIAM), Philadelphia, PA, 1999.

[6] M. F. Neuts. Matrix-geometrix solutions in stochastic models. The John Hopkins University Press, 1981.

38

Figure 9: GUI example of jMarkov

[7] J. F. Prez and G. Riao. jPhase: an object- oriented tool for modeling Phase-Type distributions. In Proceedings of the SMCtools'06, October 2006. Pisa, Italy. [8] J. F. Prez and G. Riao. jPhase user's guide. In Proceedings of the SMCtools'06, October 2006. Pisa, Italy. [9] G. Riao and J. Gez. jMarkov user's guide. Industrial Engineering, Universidad de los Andes, 2005. [10] G. Riao and A. Sarmiento. jMDP: an object-oriented framework for modeling MDPs. Working paper. Universidad de los Andes, 2006. [11] A. Sarmiento and G. Riao. jMDP user's guide. Industrial Engineering, Universidad de los Andes, 2005.

File DriveThru.java
MEASURES OF P E R F O R M A N C E

N A M E

M E A N

SDEV

Expected Server

Level

0.14286 0.12500

? 0.33072

Utilization

Figure 10: MOPs report of jMarkov

39

[12] Sun Microsystems. Java technology. Webpage:

http://www.java.sun.com/,

Jan. 2006.

[13] P. van der Linden. Just Java(TM) 2. Prentice Hall, 6th edition, 2004.

40

Index

active, 3 dests, 3 rate, 3


CTMC, 2 DTMC, 2 Generator Matrix, 2 Markov Decision Processes, 2 MDP, 2 Object Oriented Programming, 4 OOP, 4 PH, 2 Phase-Type Distributions, 2 QBD, 2 Quasi-Birth and Death Processes, 2

41

Anda mungkin juga menyukai