Run Code
|
API
|
Code Wall
|
Misc
|
Feedback
|
Login
|
Theme
|
Privacy
|
Patreon
DESim Example with Hash Table
#include <iostream> #include <string> #include <vector> #include <queue> #include <unordered_map> using namespace std; // Define the time data type #define TimeType int // Define constants used in our simulation #define TEST_SIZE 40 #define NUM_NAMES 6 string firstNames[NUM_NAMES] = {"Alice","Ambroise","Bert","Denise","Larry","Emily"}; string lastNames[NUM_NAMES] = {"Ghosh","Jones","Lee","Smith","Zhang","Zuckerman"}; #define SIM_LENGTH 100 #define MAX_DURATION 10 #define NUM_TELLERS 4 // Define event types typedef enum {ARRIVAL, DEPARTURE} EventType; // Define an event struct to store events typedef struct { string customerName; TimeType arrivalTime; // time the customer walks in the door TimeType eventTime; // could be either arrival or departure time, used in priority queue TimeType startTime; // actual time the customer gets a teller TimeType duration; EventType eventType; } EventStruct; // Define an stats struct to store statistics typedef struct { int numTransactions; TimeType totalDuration; TimeType totalWaitTime; vector<TimeType> waitTimes; } StatsStruct; // A standard way of printing events void printEvent(const EventStruct & event) { cout << event.customerName; cout << ", Event Time: " << event.eventTime; cout << ", Duration: " << event.duration; cout << ", Event type: "; if (event.eventType==ARRIVAL) cout << "ARRIVAL"; else cout << "DEPARTURE"; } // How to compare event times for the priority queue struct compareEventTime { bool operator()(const EventStruct& lhs, const EventStruct& rhs) const { return lhs.eventTime > rhs.eventTime; } }; // Our Discrete Event Simulation class class DESim { private: // event queue -- priority queue with events queued by event time priority_queue<EventStruct,vector<EventStruct>,compareEventTime> eventQueue; // wait queue -- priority queue with waiting customers queued by arrival time queue<EventStruct> bankQueue; // statsDB -- a hash table to store statistics on each customer's bank visits unordered_map<string,StatsStruct> statsDB; TimeType currentTime = 0; TimeType totalDurationAssigned = 0; TimeType tellerQuitingTime = SIM_LENGTH; bool debugOn = false; int tellersAvailable = NUM_TELLERS; public: void addArrivalEvent(); void addDepartureEvent(EventStruct & event); void addBankQueueCustomer(const EventStruct & event); void updateCustomerDB(const EventStruct & event); void setDebugOn(bool value) {debugOn = value;}; void printTime() {cout << "[" << currentTime << "] ";}; void printTellerNumberChange(); void printStats(); void runSim(); }; // end DESim // Add an arrival priority queue event void DESim::addArrivalEvent() { EventStruct myEvent; myEvent.customerName = firstNames[rand()%NUM_NAMES] + string(" ") + lastNames[rand()%NUM_NAMES]; myEvent.arrivalTime = rand()%SIM_LENGTH+1; myEvent.eventTime = myEvent.arrivalTime; // the event is an arrival, so use this time myEvent.startTime = -1; myEvent.duration = rand()%MAX_DURATION+1; myEvent.eventType = ARRIVAL; totalDurationAssigned += myEvent.duration; if (debugOn) {printTime(); cout << "Adding event: "; printEvent(myEvent); cout << endl;} eventQueue.push(myEvent); } // Add a departure priority queue event void DESim::addDepartureEvent(EventStruct & event) { event.startTime = currentTime; event.eventTime = event.startTime + event.duration; event.eventType = DEPARTURE; if (debugOn) {printTime(); cout << "Adding event: "; printEvent(event); cout << endl;} eventQueue.push(event); updateCustomerDB(event); if (event.eventTime > tellerQuitingTime) tellerQuitingTime = event.eventTime; } // Add a bank queue customer to wait for a teller (not a priority queue event) void DESim::addBankQueueCustomer(const EventStruct & event) { if (debugOn) {printTime(); cout << "Adding bank queue customer: "; printEvent(event); cout << endl;} bankQueue.push(event); } // Update stats DB with a customer's experience at our bank void DESim::updateCustomerDB(const EventStruct & event) { // compute the wait time (if any) based on the current time... TimeType waitTime = currentTime - event.arrivalTime; // before C++11 had to do the following; however, now can use "auto" data type! // unordered_map<string,int>::const_iterator hashTablePointer = customerHashTable.find(customerName); auto hashTablePointer = statsDB.find(event.customerName); if (hashTablePointer == statsDB.end() ) { if (debugOn) {printTime(); cout << event.customerName << " not found in customer DB " << endl;} StatsStruct stats; stats.numTransactions = 1; stats.totalDuration = event.duration; stats.totalWaitTime = waitTime; stats.waitTimes.push_back(waitTime); statsDB[event.customerName] = stats; } else { if (debugOn) {printTime(); cout << event.customerName << " found in customer DB " << endl;} statsDB[event.customerName].numTransactions++; statsDB[event.customerName].totalDuration += event.duration; statsDB[event.customerName].totalWaitTime += waitTime; statsDB[event.customerName].waitTimes.push_back(waitTime); } } // Print the customer statistics from the customer DB void DESim::printStats() { TimeType totalDurationSimulated = 0; for (auto local_it = statsDB.begin(); local_it!= statsDB.end(); ++local_it) { cout << "Customer Name: " << local_it->first << endl; cout << " Number of transactions: " << local_it->second.numTransactions << endl; cout << " Total duration: " << local_it->second.totalDuration << endl; cout << " Total wait time: " << local_it->second.totalWaitTime << endl; cout << " Wait Times: "; for(int i = 0; i < local_it->second.waitTimes.size(); i++){ cout << local_it->second.waitTimes[i] << " "; } cout << endl << endl; totalDurationSimulated += local_it->second.totalDuration; } cout << "\nTotal duration scheduled: " << totalDurationSimulated << endl; cout << "Total duration simulated: " << totalDurationAssigned << endl << endl; cout << "Teller quiting time: " << tellerQuitingTime << endl; cout << "Teller utilization: " << (float) totalDurationAssigned / ((float)(NUM_TELLERS * tellerQuitingTime)) << endl; } // Indicate that the number of available tellers has changed for debugging void DESim::printTellerNumberChange() { if (debugOn) {cout << "[" << currentTime <<"] Current number of tellers available: " << tellersAvailable << endl;} } // Run the simulation void DESim::runSim() { while (!eventQueue.empty()) { EventStruct nextEvent = eventQueue.top(); // get next event in priority queue currentTime = nextEvent.eventTime; eventQueue.pop(); switch (nextEvent.eventType) { case ARRIVAL: if (tellersAvailable) { // enter departure event in eventQueue addDepartureEvent(nextEvent); tellersAvailable--; printTellerNumberChange(); } else { // no tellers available, put customer in bank queue addBankQueueCustomer(nextEvent); } break; case DEPARTURE: if(!bankQueue.empty()) { EventStruct nextCustomer = bankQueue.front(); bankQueue.pop(); addDepartureEvent(nextCustomer); } else { tellersAvailable++; printTellerNumberChange(); } break; default: cout << "ERROR: Should never get here! " << endl; } } } int main() { cout << "*** Discrete Event Simulation Example for ECE 2574 ***\n\n"; DESim mySim; mySim.setDebugOn(true); srand(123321); cout << "Adding " << TEST_SIZE << " events...\n"; for (int i=0; i<TEST_SIZE; i++) { mySim.addArrivalEvent(); } cout << "\nRunning the DES...\n"; mySim.runSim(); cout << "\nPrinting out the customer statistics and teller utilization...\n"; mySim.printStats(); return 0; }
run
|
edit
|
history
|
help
0
Template Meta Programming
Sum of Natural Numbers using loop
C++17 function traits not works
New wall
enum operator
Check if a year is leap year or not
Clang-IsBaseOf
Narrowing error
Integer conversions
Member inheritance