0% found this document useful (0 votes)
19 views

Discrete Event Simulation

Uploaded by

Muhammad Shafiq
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views

Discrete Event Simulation

Uploaded by

Muhammad Shafiq
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 75

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

I got here I got here I got here


third! second! first!

This is the tail This is the


of the queue front or head
of the queue
First-in-First-out
 New items only get added to the tail.
• Never in the middle
 Items only get removed from the head.

I got here I got here I got here


third! second! first!

This is the tail This is the


of the queue front or head
of the queue
As items leave, the head shifts

I got here I got here I got here


third! second! first! AND
NOW I’M UP!

This is the tail Now, this is


of the queue the front or
head of the Served!
queue
As new items come in, the tail
shifts

I got here I got here I got here


fourth! third! second!

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

/** Push an object onto the Queue */


public void push(Object element){
elements.addFirst(element);
We’re using a linked
} list to implement the
Queue.
/** Peek at, but don't remove, top of queue */
public Object peek(){
return elements.getLast();}
The front of the
LinkedList is the tail.
/** Pop an object from the Queue */
public Object pop(){ The last of the
Object toReturn = this.peek(); LinkedList is the
elements.removeLast();
return toReturn; head.
}

/** Return the size of a queue */


public int size() { return elements.size();}
A queue is a queue, no matter
what lies beneath.
 Our description of the queue minus the
implementation is an example of an abstract
data type (ADT).
• An abstract type is a description of the methods that a
data structure knows and what the methods do.
 We can actually write programs that use the
abstract data type without specifying the
implementation.
• There are actually many implementations that will
work for the given ADT.
• Some are better than others.
Array-oriented Queue
/**
* Implements a simple queue
**/
public class Queue2 {

private static int ARRAYSIZE = 20;

/** Where we'll store our elements */


private Object[] elements;

/** The indices of the head and tail */


private int head;
private int tail;
Queue = array + head index +
tail index
/// Constructor
public Queue2(){
elements = new Object[ARRAYSIZE];
head = 0;
tail = 0;
}
/** Push an object onto the Queue */
public void push(Object element){
if ((tail + 1) >= ARRAYSIZE) {

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++; } }

/** Peek at, but don't remove, top of queue */


As the queue gets public Object peek(){
return elements[head];}
pushed and
popped, it moves /** Pop an object from the Queue */
down the array. public Object pop(){
Object toReturn = this.peek();
if (((head + 1) >= ARRAYSIZE) ||
(head > tail)) {
System.out.println("Queue underlying implementation
failed.");
return toReturn;
}
else {
// Increment the head forward, too.
head++;
return toReturn;}}

/** Return the size of a queue */


public int size() { return tail-head;}
Welcome to DrJava.
Same methods, > Queue2 line = new Queue2();
> line.push("Mary")
same behavior > line.push("Kim")
> line.push("Ron")
> line.peek()
"Mary"
But can only handle up
> line.pop()
to 20 elements in the
queue! Less if pushing "Mary"
and popping. Could shift > line.peek()
elements to always "Kim"
allow 20. > line.size()
Not as good an
2
implementation as the > line.pop()
linked list "Kim"
implementation. (But > line.pop()
uses less memory.) "Ron"
Key idea #2:
Different kinds of random
 We’ve been dealing with uniform random
distributions up until now, but those are
the least likely random distribution in real
life.
 How can we generate some other
distributions, including some that are
more realistic?
import java.util.*; // Need this for Random
import java.io.*; // For BufferedWriter
Visualizing public class GenerateUniform {

a uniform public static void main(String[] args) {


Random rng = new Random(); // Random Number Generator

distribution
BufferedWriter output=null; // file for writing

// Try to open the file


try {
// create a writer
output =
new BufferedWriter(new FileWriter("D:/cs1316/uniform.txt"));
} catch (Exception ex) {
System.out.println("Trouble opening the file.");
}
By writing out a // Fill it with 500 numbers between 0.0 and 1.0, uniformly
tab and the distributed
integer, we don’t for (int i=0; i < 500; i++){
try{
have to do the output.write("\t"+rng.nextFloat());
string conversion. output.newLine();
} catch (Exception ex) {
System.out.println("Couldn't write the data!");
System.out.println(ex.getMessage());
}
}
// Close the file
try{
output.close();}
catch (Exception ex)
{System.out.println("Something went wrong closing the file");}
}
}
How do we view a distribution?
A Histogram
Then graph the result
A Uniform Distribution
Frequency

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();

// Now, stuff it full of events, out of order.

an EventQueue SimEvent event = new SimEvent();


event.setTime(5.0);
queue.add(event);

event = new SimEvent();


event.setTime(2.0);
We’re stuffing the EventQueue queue.add(event);
with events whose times are out of
order. event = new SimEvent();
event.setTime(7.0);
queue.add(event);

event = new SimEvent();


event.setTime(0.5);
queue.add(event);

event = new SimEvent();


event.setTime(1.0);
queue.add(event);

// Get the events back, hopefull in order!


for (int i=0; i < 5; i++) {
event = queue.pop();
System.out.println("Popped event
time:"+event.getTime());
}
}
}
If it works right, should look like
this:
Welcome to DrJava.
> java EventQueueExercisor
Popped event time:0.5
Popped event time:1.0
Popped event time:2.0
Popped event time:5.0
Popped event time:7.0
Implementing an EventQueue
import java.util.*;

/**
* 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();}

public SimEvent pop(){


SimEvent toReturn = this.peek();
elements.removeFirst();
return toReturn;}

public int size(){return elements.size();}

public boolean empty(){return this.size()==0;}


Two options for add()
/**
* Add the event.
* The Queue MUST remain in order, from lowest time to
highest.
**/
public void add(SimEvent myEvent){
// Option one: Add then sort
elements.add(myEvent);
this.sort();
//Option two: Insert into order
//this.insertInOrder(myEvent);
}
There are lots of sorts!
 Lots of ways to keep things in order.
• Some are faster – best are O(n log n)
• Some are slower – they’re always O(n )
2

• Some are O(n ) in the worst case, but on


2

average, they’re better than that.


 We’re going to try an insertion sort
How an insertion sort works
 Consider the event at some position (1..n)
 Compare it to all the events before that
position backwards—towards 0.
• If the comparison event time is LESS THAN the
considered event time, then shift the comparison
event down to make room.
• Wherever we stop, that’s where the considered event
goes.
 Consider the next event…until done
Insertion Trace this out to convince yourself it
works!
Sort
public void sort(){ // While the considered event is greater than the
// Perform an insertion sort compared event ,
// it's in the wrong place, so move the
// For comparing to elements at smaller indices elements up one.
SimEvent considered = null; compareEvent = (SimEvent)
SimEvent compareEvent = null; // Just for use in
elements.get(compare-1);
loop while (compareEvent.getTime() >
// Smaller index we're comparing to considered.getTime()) {
int compare;
elements.set(compare,elements.get(compar
e-1));
// Start out assuming that position 0 is "sorted"
// When position==1, compare elements at compare = compare-1;
indices 0 and 1 // If we get to the end of the array, stop
// When position==2, compare at indices 0, 1, if (compare <= 0) {break;}
and 2, etc. // else get ready for the next time through
for (int position=1; position < elements.size(); the loop
position++){ else {compareEvent = (SimEvent)
considered = (SimEvent) elements.get(compare-1);}
elements.get(position); }
// Now, we look at "considered" versus the // Wherever we stopped, this is where
elements "considered" belongs
// less than "compare"
elements.set(compare,considered);
compare = position;
} // for all positions 1 to the end
} // end of sort()
Useful Links on Sorting
 http://ciips.ee.uwa.edu.au/~morris/Year2/
PLDS210/sorting.html
 http://www.cs.ubc.ca/spider/harrison/Jav
a/sorting-demo.html
 http://www.cs.brockport.edu/cs/java/apps
/sorters/insertsort.html Recommended

These include animations that help to


see how it’s all working
Option #2: Put it in the right
place
/**
* Add the event.
* The Queue MUST remain in order, from lowest time to
highest.
**/
public void add(SimEvent myEvent){
// Option one: Add then sort
//elements.add(myEvent);
//this.sort();
//Option two: Insert into order
this.insertInOrder(myEvent);
}
Again, trace it out to convince
yourself that it works!
insertInOrder()
/** // Assume elements from 0..i are less than
* Put thisEvent into elements, assuming thisEvent
* that it's already in order. // If the element time is GREATER,
**/ insert here and
public void insertInOrder(SimEvent // shift the rest down
thisEvent){ if (thisEvent.getTime() <
SimEvent comparison = null; comparison.getTime()) {
//Insert it here
// Have we inserted yet? inserted = true;
boolean inserted = false; elements.add(i,thisEvent);
for (int i=0; i < elements.size(); i++){ break; // We can stop the search
loop
comparison = (SimEvent) }
elements.get(i);
} // end for

// Did we get through the list without


finding something
// greater? Must be greater than any
currently there!
if (!inserted) {
// Insert it at the end
elements.addLast(thisEvent);}
Finally: A Discrete Event
Simulation
 Now, we can assemble queues, different
kinds of random, and a sorted
EventQueue to create a discrete event
simulation.
Running a DESimulation
Welcome to DrJava.
> FactorySimulation fs = new
FactorySimulation();
> fs.openFrames("D:/temp/");
> fs.run(25.0)
What we see (not much)
The detail tells the story
Time: 1.7078547183397625 Distributor: 0 Arrived at warehouse
Time: 1.7078547183397625 Distributor: 0 is blocking
>>> Timestep: 1
Time: 1.727166341118611 Distributor: 3 Arrived at warehouse
Time: 1.727166341118611 Distributor: 3 is blocking
>>> Timestep: 1
Time: 1.8778754913001443 Distributor: 4 Arrived at warehouse
Time: 1.8778754913001443 Distributor: 4 is blocking
Notice that
>>> Timestep: 1 time 2 never
Time: 1.889475045031698 Distributor: 2 Arrived at warehouse
Time: 1.889475045031698 Distributor: 2 is blocking occurs!
>>> Timestep: 1
Time: 3.064560375192933 Distributor: 1 Arrived at warehouse
Time: 3.064560375192933 Distributor: 1 is blocking
>>> Timestep: 3
Time: 3.444420374970288 Truck: 2 Arrived at warehouse with load 13
Time: 3.444420374970288 Distributor: 0 unblocked!
Time: 3.444420374970288 Distributor: 0 Gathered product for orders of 11
>>> Timestep: 3
Time: 3.8869697922832698 Truck: 0 Arrived at warehouse with load 18
Time: 3.8869697922832698 Distributor: 3 unblocked!
Time: 3.8869697922832698 Distributor: 3 Gathered product for orders of 12
>>> Timestep: 3
Time: 4.095930381479024 Distributor: 0 Arrived at market
>>> Timestep: 4
Time: 4.572840072576855 Truck: 1 Arrived at warehouse with load 20
Time: 4.572840072576855 Distributor: 4 unblocked!
What questions we can answer
 How long do distributors wait?
• Subtract the time that they unblock from the time that
they block
 How much product sits in the warehouse?
• At each time a distributor leaves, figure out how much
is left in the warehouse.
 How long does the line get at the warehouse?
• At each block, count the size of the queue.
 Can we move more product by having more
distributors or more trucks?
• Try it!
How DESimulation works
Turtle
LinkedList
-heading * +frames FrameSequence
-XPos
-YPos
+show()
+forward() 1
+replay()
+turn() 1 #agents
+setColor()
Agent -world World
+setPenDown() Simulation
#speed
1 #output
+init() 1 +setPicture()
+getAgents()
+die()
*
#simulation +add() 1
+getClosest()
+remove()
+countInRange() EventQueue
+openFrames()
+act() *
1 +setUp()
*
+openFile() -events +peek()
Queue +run() +add()
+endStep() +pop()
-blocked +lineForFile()
+push() 1 +size()
+closeFile() +empty()
+peek()
+pop() 1 +insertInOrder()
+empty() * +sort()
DEAgent +size()
-blocked Resource
+isBlocked() -amount
+isReady()
+amountAvailable() DESimluation
+validTime()
+consume()
+waitFor() -now
+add()
+unblocked() +getTime() *
+addToList()
+processEvent() +addEvent()
+log()
+run()
FactorySimulation: Extend a few
classes
Turtle
LinkedList
-heading * +frames FrameSequence
-XPos
-YPos
+show()
+forward() 1
+replay()
+turn() 1 #agents
+setColor()
Agent -world World
+setPenDown() Simulation
#speed
1 #output
+init() 1 +setPicture()
+getAgents()
+die()
*
#simulation +add() 1
+getClosest()
+remove()
+countInRange() EventQueue
+openFrames()
+act() *
1 +setUp()
*
Queue +openFile() -events +peek()
+run() +add()
-blocked +endStep() +pop()
+push() +lineForFile()
DEAgent 1 +size()
+peek() * +closeFile() +empty()
-blocked +pop() 1
+insertInOrder()
+isBlocked() +empty()
Resource +sort()
+isReady() +size()
+validTime() -amount
DESimluation
+waitFor() +amountAvailable()
+unblocked() +consume() -now
+processEvent() +add() +getTime() *
+addToList() +addEvent()
+log()
Distributor +run()
Truck -amountOrdered

-load +newOrders() -factory


+timeToDeliver() FactoryProduct
+newLoad() +tripTime()
+tripTime() FactorySimulation
+init() 1
+init() +processEvents()
+processEvents() +isReady() +setUp()
+unblocked() *
+getFactory()
DESimulation: Sets the Stage
 DESimulation calls setUp to create
agents and schedule the first events.
 It provides log for writing things out to
the console and a text file.
 When it run()’s, it processes each event
in the event queue and tells the
corresponding agent to process a
particular message.
What a DESimulation does:
// While we're not yet at the stop time,
// and there are more events to process
while ((now < stopTime) && (!events.empty())) {
topEvent = events.pop();

// Whatever event is next, that time is now As long as there are


now = topEvent.getTime();
// Let the agent now that its event has occurred
events in the queue,
topAgent = topEvent.getAgent(); and we’re not at the
topAgent.processEvent(topEvent.getMessage()); stopTime:

// repaint the world to show the movement Grab an event.


// IF there is a world
if (world != null) {
Make it’s time “now”
world.repaint();} Process the event.
// Do the end of step processing
this.endStep((int) now);
}
What’s an Event (SimEvent)?
/**
* SimulationEvent (SimEvent) -- an event that occurs in a simulation,
* like a truck arriving at a factory, or a salesperson leaving the It’s a time, an
* market
**/
Agent, and an
public class SimEvent{ integer that the
/// Fields /// Agent will
/** When does this event occur? */ understand as a
public double time; message
/** To whom does it occur? Who should be informed when it occurred? */
public DEAgent whom;

/** 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 {

/////// Constants for Messages


public static final int FACTORY_ARRIVE = 0;
public static final int WAREHOUSE_ARRIVE = 1;

////// Fields /////


/**
* Amount of product being carried
**/
public int load;
How Trucks start
/**
* Set up the truck
* Start out at the factory
**/
public void init(Simulation thisSim){
// Do the default init
super.init(thisSim);
this.setPenDown(false); // Pen up The truck gets a load,
this.setBodyColor(Color.green); // Let green deliver!
then schedules itself
// Show the truck at the factory to arrive at the
this.moveTo(30,350); Warehouse.
// Load up at the factory, and set off for the warehouse
load = this.newLoad();
((DESimulation) thisSim).addEvent(
new SimEvent(this,tripTime(),WAREHOUSE_ARRIVE));
}
tripTime() uses the normal
distribution
/** A trip distance averages 3 days */
public double tripTime(){
double delay = randNumGen.nextGaussian()+3;
if (delay < 1)
// Must take at least one day
{return 1.0+((DESimulation) simulation).getTime();}
else {return delay+((DESimulation) simulation).getTime();}
}
newLoad() uses uniform
/** A new load is between 10 and 20 on a
uniform distribution */
public int newLoad(){
return 10+randNumGen.nextInt(11);
}
How a Truck processes Events
/**
* Process an event.
* Default is to do nothing with it.
**/
public void processEvent(int message){
switch(message){
case FACTORY_ARRIVE:
// Show the truck at the factory
((DESimulation) simulation).log(this.getName()+"\t Arrived at factory");
this.moveTo(30,350);
// Load up at the factory, and set off for the warehouse
load = this.newLoad();
((DESimulation) simulation).addEvent(
new SimEvent(this,tripTime(),WAREHOUSE_ARRIVE));
break;
Truck Arriving at the Warehouse
case WAREHOUSE_ARRIVE:
// Show the truck at the warehouse
((DESimulation) simulation).log(this.getName()+"\t Arrived at
warehouse with load \t"+load);
this.moveTo(50,50);
// Unload product -- takes zero time (unrealistic!)
((FactorySimulation) simulation).getFactory().add(load);
load = 0;
// Head back to factory
((DESimulation) simulation).addEvent(
new SimEvent(this,tripTime(),FACTORY_ARRIVE));
break;
}
What Resources do
 They keep track of what amount they have
available (of whatever the resource is).
 They keep a queue of agents that are blocked
on this resource.
 They can add to the resource, or have it
consume(d).
• When more resource comes in, the head of the queue
gets asked if it’s enough. If so, it can unblock.
How Resources alert agents
/**
* Add more produced resource.
* Is there enough to unblock the first
* Agent in the Queue?
**/
public void add(int production) {
amount = amount + production;

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 {

/////// Constants for Messages


public static final int MARKET_ARRIVE = 0;
public static final int MARKET_LEAVE = 1;
public static final int WAREHOUSE_ARRIVE = 2;

/** AmountOrdered so-far */


int amountOrdered;
Distributors start in the Market
public void init(Simulation thisSim){
//First, do the normal stuff
super.init(thisSim);
this.setPenDown(false); // Pen up
this.setBodyColor(Color.blue); // Go Blue!

// Show the distributor in the market


this.moveTo(600,460); // At far right
// Get the orders, and set off for the warehouse
amountOrdered = this.newOrders();
((DESimulation) thisSim).addEvent(
new SimEvent(this,tripTime(),WAREHOUSE_ARRIVE));
}
Distributors have 3 events
 Arrive in Market: Schedule how long it’ll
take to deliver.
 Leave Market: Schedule arrive at the
Factory
 Arrive at Warehouse: Is there enough
product available? If not, block and wait
for trucks to bring enough product.
Processing Distributor Events
/**
* Process an event.
* Default is to do nothing with it.
**/
public void processEvent(int message){
switch(message){
case MARKET_ARRIVE:
// Show the distributor at the market, far left
((DESimulation) simulation).log(this.getName()+"\t Arrived at
market");
this.moveTo(210,460);
// Schedule time to deliver
((DESimulation) simulation).addEvent(
new SimEvent(this,timeToDeliver(),MARKET_LEAVE));
break;
Leaving the Market
case MARKET_LEAVE:
// Show the distributor at the market, far right
((DESimulation) simulation).log(this.getName()+"\t
Leaving market");
this.moveTo(600,460);
// Get the orders, and set off for the warehouse
amountOrdered = this.newOrders();
((DESimulation) simulation).addEvent(
new
SimEvent(this,tripTime(),WAREHOUSE_ARRIVE));
break;
Arriving at the Warehouse
case WAREHOUSE_ARRIVE:
// Show the distributor at the warehouse
((DESimulation) simulation).log(this.getName()+"\t Arrived at warehouse");
this.moveTo(600,50);
// Is there enough product available?
FactoryProduct factory = ((FactorySimulation) simulation).getFactory();
if (factory.amountAvailable() >= amountOrdered)
{
// Consume the resource for the orders
factory.consume(amountOrdered); // Zero time to load?
((DESimulation) simulation).log(this.getName()+"\t Gathered product for orders
of \t"+amountOrdered);
// Schedule myself to arrive at the Market
((DESimulation) simulation).addEvent(
new SimEvent(this,tripTime(),MARKET_ARRIVE));
}
else {// We have to wait until more product arrives!
((DESimulation) simulation).log(this.getName()+"\t is blocking");
waitFor(((FactorySimulation) simulation).getFactory());}
break;
Is there enough product?
/** Are we ready to be unlocked? */
public boolean isReady(Resource res) {
// Is the amount in the factory more than our orders?
return ((FactorySimulation) simulation).getFactory().
amountAvailable() >= amountOrdered;}
If so, we’ll be unblocked
/**
* I've been unblocked!
* @param resource the desired resource
**/
public void unblocked(Resource resource){
super.unblocked(resource);

// Consume the resource for the orders


((DESimulation) simulation).log(this.getName()+"\t unblocked!");
((FactoryProduct) resource).consume(amountOrdered); // Zero time to load?
((DESimulation) simulation).log(this.getName()+"\t Gathered product for orders of
\t"+amountOrdered);
// Schedule myself to arrive at the Market
((DESimulation) simulation).addEvent(
new SimEvent(this,tripTime(),MARKET_ARRIVE));
}
The Overall Factory Simulation
/**
* FactorySimulation -- set up the whole simulation,
* including creation of the Trucks and Distributors.
**/
public class FactorySimulation extends DESimulation {

private FactoryProduct factory;

/**
* 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")));

// Create a factory resource


factory = new FactoryProduct(); //Track factory product

// Create three trucks


Truck myTruck = null;
for (int i=0; i<3; i++){
myTruck = new Truck(world,this);
myTruck.setName("Truck: "+i);}

// Create five Distributors


Distributor sales = null;
for (int i=0; i<5; i++){
sales = new Distributor(world,this);
sales.setName("Distributor: "+i);}
}
A Class that Shouldn’t Exist
/**
* FactoryProduct -- Represents the products
* in the factory, which is the resource that
* the Truck produces and the Distributor
consumes.
**/
public class FactoryProduct extends Resource {
}
The Master Data Structure List:
We use almost everything here!
 Queues: For storing the agents waiting in
line.
 EventQueues: For storing the events
scheduled to occur.
 LinkedList: For storing all the agents.

You might also like