Skip to content

Commit

Permalink
priority queue simulation + shortest-path dijkstra graph + stl examples
Browse files Browse the repository at this point in the history
  • Loading branch information
John Blair committed May 17, 2015
1 parent 2daa791 commit 0778481
Show file tree
Hide file tree
Showing 19 changed files with 3,255 additions and 0 deletions.
136 changes: 136 additions & 0 deletions graph-dijkstra.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// http://www.math.ucla.edu/~wittman/10a.1.10w/ccc/ch23/index.html

#include <map>
#include <queue>
#include <iostream>

using namespace std;

/**
A utility class representing distance to a given city.
*/
class DistanceToCity
{
public:
DistanceToCity();
DistanceToCity(string n, int d);
bool operator<(const DistanceToCity& right) const;
string get_name() const;
int get_distance() const;
private:
string name;
int distance;
};

DistanceToCity::DistanceToCity()
{
name = "";
distance = 0;
}

DistanceToCity::DistanceToCity(string n, int d)
{
name = n;
distance = d;
}

bool DistanceToCity::operator<(const DistanceToCity& right) const
{
return right.distance < distance;
}

inline string DistanceToCity::get_name() const { return name; }

inline int DistanceToCity::get_distance() const { return distance; }

/**
A framework for finding shortest paths
using Dijkstra's shortest path algorithm.
*/
class DistanceFinder
{
public:
/**
Set the distance between two cities.
@param from originating city
@param to destination city
@param distance distance between cities
*/
void set_distance(string from, string to, int distance);

/**
Produce map of shortest distances.
@param start originating city
@param shortest map of shortest distances from start
*/
void find_distance(string start, map<string, int>& shortest);

private:
typedef multimap<string, DistanceToCity> CityMap;
typedef CityMap::iterator Citr;
CityMap cities;
};

void DistanceFinder::set_distance(string from, string to, int distance)
{
cities.insert(CityMap::value_type(from, DistanceToCity(to,
distance)));
}

void DistanceFinder::find_distance(string start,
map<string, int>& shortest)
{
priority_queue<DistanceToCity> que;
que.push(DistanceToCity(start, 0));

while (!que.empty())
{
DistanceToCity new_city = que.top();
que.pop();
if (shortest.count(new_city.get_name()) == 0)
{
int d = new_city.get_distance();
shortest[new_city.get_name()] = d;
Citr p = cities.lower_bound(new_city.get_name());
Citr stop = cities.upper_bound(new_city.get_name());
while (p != stop)
{
DistanceToCity next_destination = (*p).second;
int total_distance = d + next_destination.get_distance();
que.push(DistanceToCity(next_destination.get_name(),
total_distance));
++p;
}
}
}
}

int main()
{
DistanceFinder d;
d.set_distance("Pendleton", "Phoenix", 4);
d.set_distance("Pendleton", "Pueblo", 8);
d.set_distance("Pensacola", "Phoenix", 5);
d.set_distance("Peoria", "Pittsburgh", 5);
d.set_distance("Peoria", "Pueblo", 3);
d.set_distance("Phoenix", "Peoria", 4);
d.set_distance("Phoenix", "Pittsburgh", 10);
d.set_distance("Phoenix", "Pueblo", 3);
d.set_distance("Pierre", "Pendleton", 2);
d.set_distance("Pittsburgh", "Pensacola", 4);
d.set_distance("Princeton", "Pittsburgh", 2);
d.set_distance("Pueblo", "Pierre", 3);

map<string, int> shortest;
d.find_distance("Pierre", shortest);
map<string, int>::iterator current = shortest.begin();
map<string, int>::iterator stop = shortest.end();
while (current != stop)
{
pair<string, int> p = *current;
cout << "distance to " << p.first << " is " << p.second << "\n";
++current;
}
return 0;
}

199 changes: 199 additions & 0 deletions pq10-sim.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
// http://www.math.ucla.edu/~wittman/10a.1.10w/ccc/ch23/index.html

// GB priority_queue simulation example

// 23.5.1 Priority Queue - Example

// Event loop - the heart of the simulation
// It pulls the next event (smallest time) from the PQ
// Events are removed in sequence, regardless of insertion
// As each event is removed it is executed, and the memory recovered
// The loop runs until the the queue is exhausted

// event.h

#ifndef EVENT_H
#define EVENT_H

#include <vector>
#include <queue>
#include <iostream>
#include <cstdlib> // GB rand

using std::priority_queue;
using std::vector;

/**
A single event for a discrete event driven simulation.
*/
class Event
{
public:
Event(int t);

/**
Perform one event in the simulation.
*/
virtual void do_event() = 0;

protected:
friend class EventComparison;
int time;
};

/**
Compare two events based on their time.
*/
class EventComparison
{
public:
bool operator()(const Event* left, const Event* right) const;
};

inline int rand_int(int a, int b)
{
return a + rand() % (b - a + 1);
}

inline Event::Event(int t) : time(t) {}

inline bool EventComparison::operator()
(const Event* left, const Event* right) const
{
return left->time > right->time;
}

/**
Simulation framework for event driven simulation.
*/
class Simulation
{
public:
/**
Add new event to simulation.
@param new_event the event to add
*/
void schedule_event(Event* new_event);

/**
Run the simulation through all events.
*/
void run();
private:
priority_queue<Event*, vector<Event*>, EventComparison> event_queue;
};

inline void Simulation::schedule_event(Event* new_event)
{
event_queue.push(new_event);
}

#endif

// event.cpp

// #include "event.h"
using namespace std;
void Simulation::run()
{
while(!event_queue.empty())
{
Event* next_event = event_queue.top();
event_queue.pop();
next_event->do_event();
delete next_event;
}
}

/**
Simulation of a hot dog stand with limited seating
*/
class HotDogStand : public Simulation
{
public:
HotDogStand(int s);
/**
Test to see if new customer can be seated.
@return true if customer is seated
*/
bool can_seat();

/**
Satisfied customer leaves, having eaten.
*/
void customer_leaves();
private:
int free_seats;
};

HotDogStand::HotDogStand(int s) : free_seats(s) {}

bool HotDogStand::can_seat()
{
if (free_seats > 0)
{
free_seats--;
return true;
}
else
return false;
}

void HotDogStand::customer_leaves()
{
free_seats++;
}

HotDogStand freds(3);

/**
Arrival event for simulation.
Either customer is seated, or leaves without eating.
*/
class ArriveEvent : public Event
{
public:
ArriveEvent(int t);
virtual void do_event();
};

/**
Leave event for simulation.
Satisfied customer leaves and releases seat.
*/
class LeaveEvent : public Event
{
public:
LeaveEvent(int t);
virtual void do_event();
};

ArriveEvent::ArriveEvent(int t) : Event(t) {}

void ArriveEvent::do_event()
{
if (freds.can_seat())
{
cout << "time " << time << " Customer is seated\n";
freds.schedule_event(new LeaveEvent(time + rand_int(1, 5)));
}
else
cout << "time " << time
<< " Customer is unable to find a seat, leaves\n";
}

LeaveEvent::LeaveEvent(int t) : Event(t) {}

void LeaveEvent::do_event()
{
cout << "time " << time << " Customer finishes eating, leaves\n";
freds.customer_leaves();
}

int main()
{
for (int i = 0; i < 50; i++)
freds.schedule_event(new ArriveEvent(rand_int(1, 60)));
freds.run();
return 0;
}
Loading

0 comments on commit 0778481

Please sign in to comment.