We explain how to use the framework by providing an example. The source code can be found here. Below, we show the source with comments following each sections.
1 # 2 # Cashier example 3 # 4 5 # location of simulator 6 import sys, os 7 sys.path.append(os.pardir + os.sep + 'es') 8 9 # frame work modules 10 from sim import * 11 from model import * 12 from event import * 13 14 from rng import * 15Line 14 is required only if the Random Number Generator is used. All other lines should be common to all ES model description.
16 # constants 17 IDLE = Utilization.IDLE 18 BUSY = Utilization.BUSY 19 end_time = 100 20 21 # priorities 22 LOW = 1 23 HIGH = 2 24 25 # Random Number Generator 26 rng_10_2 = IntUniform(mean = 10, spread = 2) 27 28 29 # a flag to make it run with or without priorities 30 priorityOn = 0 31 32 # 33 # This is a start event. It will be the first 34 # event scheduled. 35 # 36 class MyStartEvent(StartEvent): 37
The model is described in terms of classes that extend Event or one of its subclasses. Each model should have at least one class that extends the class StartEvent. An instance of this class will be the first event scheduled by the simulator.
38 # handler routine 39 def execute(self, sched, state): 40 # create state variables and add then to 41 # the state set 42 state.add(QueueVar("queue_length")) 43 state.add(Utilization("cashier_state", IDLE)) 44 45 # schedule the first arrival at time 0 46 sched.schedule(ArrivalEvent(0)) 47 # schedule the end event at time end_time 48 sched.schedule(StatsEndEvent(end_time)) 49 50
The handler routine has the method signature execute(self, sched, state). Its purpose is to change the state and/or shedule new events. It is invoked by the simulator kernel when it is time for this event to occur. The simulator will pass two arguments to it. sched is an object of type Scheduler that provides methods to schedule events. state is a State instance. It provides methods to access and modify the state variables. The execute method provided by the Event does nothing by default. In most cases, you would want to override it to do useful thing.
Each state variable has a name and a value. Different types of state variables are already defined. The user can also define its own type by extending StateVar. A variable of type StateVar is the most general type. More specialized types such as QueueVar can be used. These special types have methods that keeps track and compute useful performance metrics. All state variables should be added to the state object at the beginning, i.e. in the start event execute() method. A state variable called current_time will be added when the simulation will start. It contains the current time and it is updated by the kernel.
Events are scheduled by creating an instance of the event and passing it to the schedule() method of the Scheduler. The default constructor takes the time as an argument. The time is always an absolute time. Note that the scheduler is aware of the current time and will not allow an event to be scheduled in the past, it will raise an error. We have provided two end events with our framework. The user can extend EndEvent to create its own. EndEvents are special events known by the kernel. They will stop the simulation (all events scheduled at the same time than the end event will be executed before it is executed and the simulation terminates). The StatsEndEvent is an end event that prints all the performance metrics to standard output.
51 52 # represents the arrival of a customer 53 class ArrivalEvent(Event): 54 55 def __init__(self, time): 56 Event.__init__(self, time) 57 if priorityOn: 58 self.setPriority(LOW) 59
If a constructor is provided, it should invoke the super constructor with a time argument. The priorityOn condition was used only to allow us to run the simulation with different priorities are all the same. A small note about priorities: priorities are per event type and not per event instance.
60 61 # handler routine 62 def execute(self, sched, state): 63 # current time 64 time = self.getTime() 65
The current time can be accessed either with getTime() or via the current_time state variable: state.getValue("current_time")
66 # get variables needed 67 queue = state.getStateVar("queue_length") 68 cashier_state = state.getStateVar("cashier_state")
It is not necessary to "extract" a state variables from the state to read or change its value. See the State API
69 70 sched.schedule(ArrivalEvent(time + rng_10_2.next())) 71 if (queue.isEmpty()): 72 if (cashier_state.isIdle()): 73 cashier_state.setValue(BUSY) 74 sched.schedule(DepartureEvent(time + 25)) 75 else: 76 # note: 77 # This simply increases the queue length by 1. 78 # No object is actually enqueued. 79 # It is equivalent to: 80 # queue.setValue(queue.getValue() + 1) 81 queue.enqueue() 82 else: 83 queue.enqueue() 84 85 86 class DepartureEvent(Event): 87 88 def __init__(self, time): 89 Event.__init__(self, time) 90 if priorityOn: 91 self.setPriority(HIGH) 92 93 94 def execute(self, sched, state): 95 time = self.getTime() 96 queue = state.getStateVar("queue_length") 97 cashier_state = state.getStateVar("cashier_state") 98 99 if (queue.isEmpty()): 100 # note: equivalent to: cashier_state.setValue(IDLE) 101 cashier_state.releaseFacility() 102 else: 103 queue.dequeue() 104 sched.schedule(DepartureEvent(time + 25)) 105 106 107 # 108 # Construct a model object. 109 # An instance of our start event is required. 110 # An optional name may be given. 111 # 112 # This model is passed on to the simulator. 113 # 114 mymodel = Model(MyStartEvent(), "Super Market") 115 simulator = Simulator(mymodel) 116
The instance of the start event created will be the first event scheduled when the simulation will run. The name argument is optional.
117 118 if __name__ == "__main__": 119 if len(sys.argv) > 1: 120 if sys.argv == 'p': 121 print "Using priorities" 122 priorityOn = 1 123 simulator.setTrace() # turn on trace mode, default output file 124 simulator.run() # simulates 125
These few lines turns the trace on and starts the simulation. Since no filename has been specified, it will use the default file name temp.txt.
Our Visual Tool has been used to plot graphs from the data in the trace file.
Queue length vs time
Cashier state vs time (0 - Idle, 1 - Busy)
A second example is shown at the end of the ESHLL section.
- source code. - running result. - the time vs. queue length plotting:
$Id: framework.html,v 220.127.116.11 2003/03/22 05:15:49 dbelan2 Exp $