Assignment 5: ANSI C++ familiarization; graph plotting; typesetting Write a discrete event simulator using ANSI C++ classes to make your code simple and small. The scenario being simulated is a bank where customers arrive according to a Poisson process. There is one queue and a number of counters. The customer at the head of the queue is assigned to a free counter uniformly at random. Service time at each counter is exponentially distributed. Your goal is to implement the simulator in as few lines of (your) code as possible, make it efficient, and experiment with various combination of parameter values (arrival rate, number of queues, service time) and plot average queue length, average waiting time, fraction of time that the queue was bigger than a set threshold, etc. This graphs are to be included in a very short report together with all formulae and pseudocode; typeset this report in LaTeX and turn in the PS file. #include #include #include #ifdef _WIN32 using namespace std; #endif int main( int argc, char *argv[] ) { int ival, nitems = 0; vector v; cout << "Enter integers, after each, Z to finish:" << endl; while( cin >> ival, cin.good() ) { v.push_back( ival ); cout.width(6); cout << nitems << ": " << v[nitems++] << endl; } if ( nitems ) { sort( v.begin(), v.end() ); for (vector::const_iterator viter=v.begin(); viter!=v.end(); ++viter) cout << *viter << " "; cout << endl; } return( EXIT_SUCCESS ); } Polymorphism #define COMPARE_VALUES( value_type ) \ value_type compare_values_##value_type( const void *a, const void *b ) \ {const value_type *first, *second; \ first = (value_type *)a; second = (value_type *)b; return( *first - *second );} COMPARE_VALUES( float ) /* Generate function for floats, */ COMPARE_VALUES( double ) /* doubles and */ COMPARE_VALUES( int ) /* ints */ . /* Pick comparison function */ qsort( v, nitems, sizeof(array_type), compare_values_int ); Instead ... template T mymin( T v1, T v2) { return( (v1 < v2) ? v1 : v2 ); } Some Vector Access Functions Purpose ---------------------------- ------- begin() Returns iterator pointing to first element end() Returns iterator pointing _after_ last element push_back(...) Add element to end of vector pop_back(...) Destroy element at end of vector swap( , ) Swap two elements insert( , ) Insert new element size() Number of elements in vector capacity() Element capacity before more memory needed empty() True if vector is empty [] Random access operator #include #include #include #ifdef _WIN32 using namespace std; #endif int main( int argc, char *argv[] ) { stack< const char *, vector > s; // Push on stack in reverse order s.push("order"); s.push("correct"); // Oh no it isn't ! s.push("the"); s.push("in"); s.push("is"); s.push("This"); // Pop off stack which reverses the push() order while ( !s.empty() ) { cout << s.top() << " "; s.pop(); /// Oh yes it is ! } cout << endl; return( EXIT_SUCCESS ); } Stack ops Container Function Priority Queue Adapter Function ------------------ ------------------------------- front() top() push_back() push() pop_back() pop() empty() empty() size() size() [] random iterators Required to support heap ordering operations Priority queue #include A priority_queue, defined in the header, is similar to a queue, with the additional capability of ordering the objects according to a user-defined priority. The order of objects with equal priority is not really predictable, except of course, they will be grouped together. This might be required by an operating system process scheduler, or batch queue manager. The underlying container has to support push_back(), pop_back(), empty(), front(), plus a random access iterator and comparison function to decide priority order. Container Function Priority Queue Adapter Function ------------------ ------------------------------- front() top() push_back() push() pop_back() pop() empty() empty() size() size() [] random iterators Required to support heap ordering operations Hence a vector or a deque can be used as the underlying container, or a suitable user-provided class. #include #include #include #include #include #ifdef _WIN32 using namespace std; #endif class TaskObject { public: friend class PrioritizeTasks; friend ostream & operator<<( ostream &os, TaskObject &task); TaskObject( const char *pname = "", unsigned int prio = 4 ) { process_name = pname; priority = prio; } private: unsigned int priority; string process_name; }; // Friend function for "printing" TaskObject to an output stream ostream & operator<<( ostream &os, TaskObject &task ) { os << "Process: " << task.process_name << " Priority: " << task.priority; return ( os ); } // Friend class with function object for comparison of TaskObjects class PrioritizeTasks { public : int operator()( const TaskObject &x, const TaskObject &y ) { return x.priority < y.priority; } }; int main( int argc, char *argv[] ) { int i; priority_queue, PrioritizeTasks> task_queue; TaskObject tasks[] = { "JAF", "ROB", "PHIL", "JOHN" ,TaskObject("OPCOM",6) , TaskObject("Swapper",16) ,TaskObject("NETACP",8) , TaskObject("REMACP",8) }; for ( i = 0; i < sizeof(tasks)/sizeof(tasks[0]) ; i++ ) task_queue.push( tasks[i] ); while ( !task_queue.empty() ) { cout << task_queue.top() << endl; task_queue.pop(); } cout << endl; return( EXIT_SUCCESS ); } Strings Some String Access Functions Purpose ---------------------------- ------- find(...) Find substring or character, start at start find_first_of(...) Find first occurrence of any characters in given set, starting from start of string find_last_of(...) Find last occurrence of any characters in given set, starting from start of string find_not_first_of(...) Find first occurrence of characters _not_ in given set, starting from start of string find_last_not_of(...) Find last occurrence of characters _not_ in given set, starting from start of string rfind(...) Find substring or character, start at end size() Number of elements in vector [] Random access to return a single character - no bounds checking at(...) Random access to return a single character - with bounds checking + Concatenate strings swap( , ) Swap two strings insert( , ) Insert a string at the specified position replace(...) Replace selected substring with another string Iterators list l; list::iterator liter; // Iterator for looping over list elements for ( liter = l.begin(); liter != l.end(); liter++ ) { *liter = 0; } Associative containers map multimap set multiset Some Map Access Functions Purpose ------------------------- ------- begin() Returns iterator pointing to first element end() Returns iterator pointing _after_ last element swap( , ) Swap two elements insert( , ) Insert a new element size() Number of elements in map max_size() Maximum possible number of elements in map empty() True if map is empty [] "Subscript search" access operator