Discrete Event Simulation
Discrete Event Simulation
CS1316: Representing
Structure and Behavior
Story
Discrete event simulation
• Simulation time != real time
Key ideas:
• A Queue
• A Queue is a queue, no matter how implemented.
• Different kinds of random
• Straightening time
• Inserting it into the right place
• Sorting it afterwards
Building a discrete event simulation
• Graphics as the representation, not the real thing: The
Model and the View
Imagine the simulation…
There are three Trucks that bring product from the
Factory.
• On average, they take 3 days to arrive.
• Each truck brings somewhere between 10 and 20 products
—all equally likely.
We’ve got five Distributors who pick up product from the
Factory with orders.
• Usually they want from 5 to 25 products, all equally likely.
It takes the Distributors an average of 2 days to get back
to the market, and an average of 5 days to deliver the
products.
Question we might wonder: How much product gets sold
like this?
Don’t use a Continuous
Simulation
We don’t want to wait that number of days in real time.
We don’t even care about every day.
• There will certainly be timesteps (days) when nothing
happens of interest.
We’re dealing with different probability distributions.
• Some uniform, some normally distributed.
Things can get out of synch
• A Truck may go back to the factory and get more product
before a Distributor gets back.
• A Distributor may have to wait for multiple trucks to fulfill
orders (and other Distributors might end up waiting in line)
We use a Discrete Event
Simulation
We don’t simulate every moment
continuously.
We simulate discrete events.
What’s the difference?
No time loop
In a discrete event simulation: There is
no time loop.
• There are events that are scheduled.
• At each run step, the next scheduled event
with the lowest time gets processed.
• The current time is then that time, the time that that
event is supposed to occur.
Key: We have to keep the list of
scheduled events sorted (in order)
What’s the difference?
Agents don’t act()
In a discrete event simulations, agents
don’t act().
• Instead, they wait for events to occur.
• They schedule new events to correspond to
the next thing that they’re going to do.
Key: Events get scheduled according to
different probabilities.
What’s the difference?
Agents get blocked
Agents can’t do everything that they want to do.
If they want product (for example) and there isn’t any,
they get blocked.
• They can’t schedule any new events until they get
unblocked.
Many agents may get blocked awaiting the same
resource.
• More than one Distributor may be awaiting arrival of Trucks
Key: We have to keep track of the Distributors waiting in
line (in the queue)
Key Ideas
A Queue
• A Queue is a queue, no matter how implemented.
Different kinds of random
Straightening time
• Inserting it into the right place
• Sorting it afterwards
Key idea #1:
Introducing a Queue
First-In-First-Out List
• First person in line is first person served
Now, this is
Now, this is
the tail of the
the front or
queue
head of the
queue
What can we do with queues?
push(anObject): Tack a new object onto
the tail of the queue
pop(): Pull the end (head) object off the
queue.
peek(): Get the head of the queue, but
don’t remove it from the queue.
size(): Return the size of the queue
Building a Queue
> Queue line = new Queue();
> line.push("Fred");
> line.push("Mary");
> line.push("Jose");
> line.size()
3
Accessing a Queue
> line.peek()
"Fred"
> line.pop()
"Fred"
> line.peek()
"Mary" We don’t really
> line.pop() want to peek()
"Mary" or pop() an
> line.peek() empty queue,
"Jose" so we should
> line.pop() probably check
"Jose" its size first.
> line.pop()
java.util.NoSuchElementException:
Building a
Queue
import java.util.*; // LinkedList representation
/**
* Implements a simple queue
**/
public class Queue {
/** Where we'll store our elements */
public LinkedList elements;
/// Constructor
public Queue(){
elements = new LinkedList();
}
Queue methods
/// Methods
Queue2
System.out.println("Queue underlying implementation
failed");
}
methods else {
// Store at the tail,
// then increment to a new open position
elements[tail] = element;
tail++; } }
distribution
BufferedWriter output=null; // file for writing
70
60
50
40
Frequency
30
20
10
0
0 2 4 6 8 1
0. 0. 0. 0.
A Normal
Distribution
// Fill it with 500 numbers between -1.0 and 1.0, normally distributed
for (int i=0; i < 500; i++){
try{
output.write("\t"+rng.nextGaussian());
output.newLine();
} catch (Exception ex) {
System.out.println("Couldn't write the data!");
System.out.println(ex.getMessage());
}
}
Graphing the normal distribution
Frequency
30
25
20
15 Frequency
10
5 The end aren’t
actually high—
0 the tails go
further.
6
4
-2
6
0
2
.
0.
0.
1.
1.
-1
-1
-0
-0
How do we shift the distribution
where we want it?
// Fill it with 500 numbers with a mean of 5.0 and a
//larger spread, normally distributed
for (int i=0; i < 500; i++){
try{
output.write("\t"+((range * rng.nextGaussian())+mean));
output.newLine();
} catch (Exception ex) {
System.out.println("Couldn't write the data!");
System.out.println(ex.getMessage());
}
} Multiply the random nextGaussian()
by the range you want, then add the
mean to shift it where you want it.
A new normal distribution
Frequency
18
16
14
12
10
Frequency
8
6
4
2
0
-2
-1.5
-1
-0.5
0
0.5
1
1.5
2
2.5
3
3.5
4
4.5
5
5.5
6
6.5
7
7.5
8
8.5
9
9.5
10
Key idea #3: Straightening Time
Straightening time
• Inserting it into the right place
• Sorting it afterwards
We’ll actually do these in reverse order:
• We’ll add a new event, then sort it.
• Then we’ll insert it into the right place.
public class EventQueueExercisor {
public static void main(String[] args){
// Make an EventQueue
Exercising
EventQueue queue = new EventQueue();
/**
* EventQueue
* It's called an event "queue," but it's not really.
* Instead, it's a list (could be an array, could be a linked list)
* that always keeps its elements in time sorted order.
* When you get the nextEvent, you KNOW that it's the one
* with the lowest time in the EventQueue
**/
public class EventQueue {
private LinkedList elements;
/// Constructor
public EventQueue(){
elements = new LinkedList();
}
Mostly, it’s a queue
public SimEvent peek(){
return (SimEvent) elements.getFirst();}
/** What is the event? We'll use integers to represent the meaning
* of the event -- the "message" of the event.
* Each agent will know the meaning of the integer for themselves.
**/
public int message;
DEAgent: Process events, block
if needed
DEAgents define the constants for messages:
What will be the main events for this agent?
If the agent needs a resource, it asks to see if
it’s available, and if not, it blocks itself.
It will be told to unblock when it’s ready.
Agents are responsible for scheduling their
OWN next event!
An Example: A Truck
/**
* Truck -- delivers product from Factory
* to Warehouse.
**/
public class Truck extends DEAgent {
if (!blocked.empty()){
// Ask the next Agent in the queue if it can be unblocked
DEAgent topOne = (DEAgent) blocked.peek();
// Is it ready to run given this resource?
if (topOne.isReady(this)) {
// Remove it from the queue
topOne = (DEAgent) blocked.pop();
// And tell it it’s unblocked
topOne.unblocked(this);
}
}
}
An example blocking agent:
Distributor
/**
* Distributor -- takes orders from Market to Warehouse,
* fills them, and returns with product.
**/
public class Distributor extends DEAgent {
/**
* Accessor for factory
**/
public FactoryProduct getFactory(){return factory;}
Setting up the Factory
Simulation
public void setUp(){
// Let the world be setup
super.setUp();
// Give the world a reasonable background
FileChooser.setMediaPath("D:/cs1316/MediaSources/");
world.setPicture(new Picture(
FileChooser.getMediaPath("EconomyBackground.jpg")));