Queueing simulation VBA help

deedeedudu

New Member
Joined
Dec 9, 2014
Messages
1
Dear Excel/VBA gurus,

I'm new to using VBA and we are taught queuing simulation in class. As part of the assignment we need to modify the attached code as per the following

Change the program so that the current simulation is embedded in a For Loop from 1 to 100. Each time through the loop, one simulation is run, and its output (you can select which ones) are reported on a Replications sheet. After all 100 simulations have run, summarize the selected outputs on a Summary sheet. For each output, report the following summary measures: minimum, maximum, average, standard deviation, median and 5th and 95th percentile.
For example, if one of your outputs on any replication is the maximum number in queue, then you will get 100 such maximums, one for each replication. The summary sheet should summarize these 100 numbers: their average, their standard deviation and so on. In this way you can see how results vary from replication to another.

Code:
[/COLOR]Option Explicit


' Declare system parameters.
'   meanIATime - mean interarrival time (reciprocal of arrival rate)
'   meanServeTime - mean service time
'   nServers - number of servers
'   maxAllowedInQ - maximum number of customers allowed in the queue
'   closeTime - clock time when no future arrivals are accepted


Dim meanIATime As Single
Dim meanServeTime As Single
Dim nServers As Integer
Dim maxAllowedInQ As Integer
Dim closeTime As Single
    
' Declare system status indicators.
'   nInQueue - number of customers currently in the queue
'   nBusy - number of servers currently busy
'   clockTime - current clock time, where the inital clock time is 0
'   eventScheduled(i) - True or False, depending on whether an event of type i is
'       scheduled or not, for i>=0, where i=0 corresponds to arrivals and i from
'       1 to nServers corresponds to server i service completions
'   timeOfLastEvent - clock time of previous event
'   timeOfNextEvent(i) - the scheduled clock time of the next event of type i
'       (only defined when eventScheduled(i) is True


Dim nInQueue As Integer
Dim nBusy As Integer
Dim clockTime As Single
Dim eventScheduled() As Boolean
Dim timeOfLastEvent As Single
Dim timeOfNextEvent() As Single


' Declare statistical variables.
'   nServed - number of customers who have completed service so far
'   nLost - number of customers who have been turned away so far
'   maxNInQueue - maximum number in the queue at any point in time so far
'   maxTimeInQueue - maximum time any customer has spent in the queue so far
'   timeOfArrival(i) - arrival time of the customer currently in the i-th
'       place in the queue, for i>=1
'   totalTimeInQueue - total customer-time units spent in the queue so far
'   totalTimeBusy - total server-time units spent serving customers so far
'   sumOfQueueTimes - sum of all times in the queue so far, where sum is over
'       customers who have completed their times in the queue
'   queueTimeArray(i) - amount of time there have been exactly i customers
'       in the queue, for i>=0


Dim nServed As Long
Dim nLost As Integer
Dim maxNInQueue As Integer
Dim maxTimeInQueue As Single
Dim timeOfArrival() As Single
Dim totalTimeInQueue As Single
Dim totalTimeBusy As Single
Dim sumOfQueueTimes As Single
Dim queueTimeArray() As Single


Sub Main()
    ' This sub runs when the user clicks on the "Run the simulation" button on
    ' the Simulation sheet. It sets up and runs the simulation.
    Dim nextEventType As Integer
    Dim finishedServer As Integer


    ' Always start with new random numbers.
    Randomize


    ' Clear previous results, if any, from the Report sheet.
    Call ClearOldResults


    ' Get inputs from the Report Sheet.
    meanIATime = 1 / Range("ArriveRate").Value
    meanServeTime = Range("MeanServeTime").Value
    nServers = Range("nServers").Value
    maxAllowedInQ = Range("MaxAllowedInQ").Value
    closeTime = Range("CloseTime").Value


    ' The next two arrays have an element for arrivals (index 0)
    ' and one for each server.
    ReDim eventScheduled(nServers + 1)
    ReDim timeOfNextEvent(nServers + 1)


    ' Set counters, status indicators to 0 and schedule first arrival.
    Call Initialize


    ' Keep simulating until the last customer has left.
    Do
        ' Find the time and type of the next event, and reset the clock.
        ' Capture the index of the finished server in case the next event
        ' is a service completion.
        Call FindNextEvent(nextEventType, finishedServer)


        ' Update statistics since the last event.
        Call UpdateStatistics


        ' nextEventType is 1 for an arrival, 2 for a departure.
        If nextEventType = 1 Then
            Call Arrival
        Else
            Call Departure(finishedServer)
        End If
    Loop Until Not eventScheduled(0) And nBusy = 0


    ' Report the results.
    Call Report
End Sub


Sub ClearOldResults()
    ' This sub clears the results from any previous simulation.
    With Worksheets("Report")
        .Range("B12:B23").ClearContents
        With .Range("A26")
            Range(.Offset(1, 0), .Offset(0, 1).End(xlDown)).ClearContents
        End With
    End With
End Sub


Sub Initialize()
    ' This sub initializes the simulation to the "empty and idle" state and
    ' sets all statistical counters to 0. It then schedules the first arrival.
    Dim i As Integer


    ' Initialize system status indicators.
    clockTime = 0
    nBusy = 0
    nInQueue = 0
    timeOfLastEvent = 0


    ' Initialize statistical variables.
    nServed = 0
    nLost = 0
    sumOfQueueTimes = 0
    maxTimeInQueue = 0
    totalTimeInQueue = 0
    maxNInQueue = 0
    totalTimeBusy = 0


    ' Redimension the queueTimeArray array to have one element (the 0 element,
    ' for the amount of time when there are 0 customers in the queue).
    ReDim queueTimeArray(1)
    queueTimeArray(0) = 0


    ' Schedule an arrival from the exponential distribution.
    eventScheduled(0) = True
    timeOfNextEvent(0) = Exponential(meanIATime)


    ' Don't schedule any departures because there are no customers in the system.
    For i = 1 To nServers
        eventScheduled(i) = False
    Next
End Sub


Function Exponential(mean As Single) As Single
    ' This generates a random number from an exponential distribution
    ' with a given mean.
    Exponential = -mean * Log(Rnd)
End Function


Sub FindNextEvent(nextEventType As Integer, finishedServer As Integer)
    ' This sub finds the type (arrival, departure, or closing time) of the next
    ' event and advances the simulation clock to the time of the next event.
    Dim i As Integer
    Dim nextEventTime As Single


    ' nextEventTime will be the minimum of the scheduled event times.
    ' Start by setting it to a large value.
    nextEventTime = 10 * closeTime


    ' Find type and time of the next (most imminent) scheduled event. Note that
    ' there is a potential event scheduled for the next arrival (indexed as 0) and
    ' for each server completion (indexed as 1 to nServers).
    For i = 0 To nServers
        ' Check if there is an event schedule of type i.
        If eventScheduled(i) Then
            ' If the current event is the most imminent so far, record it.
            If timeOfNextEvent(i) < nextEventTime Then
                nextEventTime = timeOfNextEvent(i)
                If i = 0 Then
                    ' It's an arrival.
                    nextEventType = 1
                Else
                    ' It's a departure - record the index of the server who finished.
                    nextEventType = 2
                    finishedServer = i
                End If
            End If
        End If
    Next


    ' Advance the clock to the time of the next event.
    clockTime = nextEventTime
End Sub
      
Sub UpdateStatistics()
    ' This sub updates statistics since the time of the previous event.
    Dim timeSinceLastEvent As Single


    ' timeSinceLastEvent is the time since the last update.
    timeSinceLastEvent = clockTime - timeOfLastEvent


    ' Update statistical variables.
    queueTimeArray(nInQueue) = queueTimeArray(nInQueue) + timeSinceLastEvent
    totalTimeInQueue = totalTimeInQueue + nInQueue * timeSinceLastEvent
    totalTimeBusy = totalTimeBusy + nBusy * timeSinceLastEvent


    ' Reset timeOfLastEvent to the current time.
    timeOfLastEvent = clockTime
End Sub


Sub Arrival()
    ' This sub takes care of all the logic when a customer arrives.
    Dim i As Integer


    ' Schedule the next arrival.
    timeOfNextEvent(0) = clockTime + Exponential(meanIATime)


    ' Cut off the arrival stream if it is past closing time.
    If timeOfNextEvent(0) > closeTime Then
        eventScheduled(0) = False
    End If


    ' If the queue is already full, this customer is turned away.
    If nInQueue = maxAllowedInQ Then
        nLost = nLost + 1
        Exit Sub
    End If


    ' Check if all servers are busy.
    If nBusy = nServers Then


        ' All servers are busy, so put this customer at the end of the queue.
        nInQueue = nInQueue + 1


        ' If the queue is now longer than it has been before, update maxNInQueue
        ' and redimension arrays appropriately.
        If nInQueue > maxNInQueue Then
            maxNInQueue = nInQueue


            ' queueTimeArray is 0-based, with elements 0 to maxNInQueue.
            ReDim Preserve queueTimeArray(0 To maxNInQueue)


            ' timeOfArrival is 1-based, with elements 1 to maxNInQueue.
            ReDim Preserve timeOfArrival(1 To maxNInQueue)
        End If


        ' Keep track of this customer's arrival time (for later stats).
        timeOfArrival(nInQueue) = clockTime


    Else
        ' The customer can go directly into service, so update the number of servers busy.
        nBusy = nBusy + 1


        ' This loop searches for the first idle server and schedules a departure
        ' event for this server.
        For i = 1 To nServers
            If Not eventScheduled(i) Then
                eventScheduled(i) = True
                timeOfNextEvent(i) = clockTime + Exponential(meanServeTime)
                Exit For
            End If
        Next
    End If
End Sub
      
Sub Departure(finishedServer As Integer)
    ' This sub takes care of the logic when a customer departs from service.
    Dim i As Integer
    Dim timeInQueue As Single


    ' Update number of customers who have finished.
    nServed = nServed + 1


    ' Check if any customers are waiting in queue.
    If nInQueue = 0 Then
        
        ' No one is in the queue, so make the server who just finished idle.
        nBusy = nBusy - 1
        eventScheduled(finishedServer) = False


    Else


        ' At least one person is in the queue, so take first customer
        ' in queue into service.
        nInQueue = nInQueue - 1


        ' timeInQueue is the time this customer has been waiting in line.
        timeInQueue = clockTime - timeOfArrival(1)


        ' Check if this is a new maximum time in queue.
        If timeInQueue > maxTimeInQueue Then
            maxTimeInQueue = timeInQueue
        End If


        ' Update the total of all customer queue times so far.
        sumOfQueueTimes = sumOfQueueTimes + timeInQueue


        ' Schedule departure for this customer with the same server who just finished.
        timeOfNextEvent(finishedServer) = clockTime + Exponential(meanServeTime)


        ' Move everyone else in line up one space.
        For i = 1 To nInQueue
            timeOfArrival(i) = timeOfArrival(i + 1)
        Next
    End If
End Sub
      
Sub Report()
    ' This sub calculates and then reports summary measures for the simulation.
    Dim i As Integer
    Dim avgTimeInQueue As Single
    Dim avgNInQueue As Single
    Dim avgNBusy As Single


    ' Calculate averages.
    avgTimeInQueue = sumOfQueueTimes / nServed
    avgNInQueue = totalTimeInQueue / clockTime
    avgNBusy = totalTimeBusy / clockTime


    ' queueTimeArray records, for each value from 0 to maxNInQueue, the percentage
    ' of time that many customers were waiting in the queue.
    For i = 0 To maxNInQueue
        queueTimeArray(i) = queueTimeArray(i) / clockTime
    Next


    ' Enter simulate results in named ranges.
    Range("FinalTime").Value = clockTime
    Range("NServed").Value = nServed
    Range("AvgTimeInQ").Value = avgTimeInQueue
    Range("MaxTimeInQ").Value = maxTimeInQueue
    Range("AvgNInQ").Value = avgNInQueue
    Range("MaxNInQ").Value = maxNInQueue
    Range("AvgServerUtil").Value = avgNBusy / nServers
    Range("NLost").Value = nLost
    Range("PctLost").Formula = "=NLost/(NLost + NServed)"


    ' Enter the queue length distribution from row 27 down, and name the two columns.
    With Range("A27")
        For i = 0 To maxNInQueue
            .Offset(i, 0).Value = i
            .Offset(i, 1).Value = queueTimeArray(i)
        Next
        Range(.Offset(0, 0), .Offset(maxNInQueue, 0)).Name = "NInQueue"
        Range(.Offset(0, 1), .Offset(maxNInQueue, 1)).Name = "PctOfTime"
    End With
    
    ' Update the chart.
    With ActiveSheet.ChartObjects(1).Chart
        With .SeriesCollection(1)
            .Values = Range("PctOfTime")
            .XValues = Range("nInQueue")
        End With
    End With


    Range("A2").Select
End Sub


Sub ViewChangeInputs()
    ' This sub runs when the user clicks on the "View/Change Inputs" button on the
    ' Explanation sheet. It clears old results, if any, and lets the user see
    ' the Report sheet.
    With Worksheets("Report")
        .Visible = True
        .Activate
    End With
    Call ClearOldResults
End Sub
 

Excel Facts

What did Pito Salas invent?
Pito Salas, working for Lotus, popularized what would become to be pivot tables. It was released as Lotus Improv in 1989.

Forum statistics

Threads
1,223,246
Messages
6,170,999
Members
452,373
Latest member
TimReeks

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top