Problem Solving with Data Structures using Java: A Multimedia Approach Chapter 17: Discrete Event Simulation.

Slides:



Advertisements
Similar presentations
Discrete Event Simulation CS1316: Representing Structure and Behavior.
Advertisements

Stacks, Queues, and Deques. 2 A stack is a last in, first out (LIFO) data structure Items are removed from a stack in the reverse order from the way they.
Priority Queues. 2 Priority queue A stack is first in, last out A queue is first in, first out A priority queue is least-first-out The “smallest” element.
Quick Sort, Shell Sort, Counting Sort, Radix Sort AND Bucket Sort
Recursion, pt. 2: Thinking it Through. What is Recursion? Recursion is the idea of solving a problem in terms of solving a smaller instance of the same.
Programming with Alice Computing Institute for K-12 Teachers Summer 2011 Workshop.
Searching Kruse and Ryba Ch and 9.6. Problem: Search We are given a list of records. Each record has an associated key. Give efficient algorithm.
CSE332: Data Abstractions Lecture 4: Priority Queues Dan Grossman Spring 2010.
This material in not in your text (except as exercises) Sequence Comparisons –Problems in molecular biology involve finding the minimum number of edit.
CS 106 Introduction to Computer Science I 02 / 28 / 2007 Instructor: Michael Eckmann.
CS 106 Introduction to Computer Science I 03 / 03 / 2008 Instructor: Michael Eckmann.
CS 106 Introduction to Computer Science I 10 / 15 / 2007 Instructor: Michael Eckmann.
CS 106 Introduction to Computer Science I 10 / 16 / 2006 Instructor: Michael Eckmann.
Georgia Institute of Technology Making Text for the Web part 4 Barb Ericson Georgia Institute of Technology March 2006.
Stacks, Queues, and Deques
Maps A map is an object that maps keys to values Each key can map to at most one value, and a map cannot contain duplicate keys KeyValue Map Examples Dictionaries:
CS 46B: Introduction to Data Structures July 30 Class Meeting Department of Computer Science San Jose State University Summer 2015 Instructor: Ron Mak.
(c) University of Washingtonhashing-1 CSC 143 Java Hashing Set Implementation via Hashing.
1 HEAPS & PRIORITY QUEUES Array and Tree implementations.
Georgia Institute of Technology Speed part 3 Barb Ericson Georgia Institute of Technology May 2006.
Georgia Institute of Technology Creating and Modifying Text part 4 Barb Ericson Georgia Institute of Technology Oct 2005.
Nachos Phase 1 Code -Hints and Comments
Iteration. Adding CDs to Vic Stack In many of the programs you write, you would like to have a CD on the stack before the program runs. To do this, you.
Week 5 - Monday.  What did we talk about last time?  Linked list implementations  Stacks  Queues.
Spring 2008 Mark Fontenot CSE 1341 Principles of Computer Science I Note Set 2.
CS 61B Data Structures and Programming Methodology July 28, 2008 David Sun.
Collecting Things Together - Lists 1. We’ve seen that Python can store things in memory and retrieve, using names. Sometime we want to store a bunch of.
1 Heaps and Priority Queues Starring: Min Heap Co-Starring: Max Heap.
P p Chapter 10 has several programming projects, including a project that uses heaps. p p This presentation shows you what a heap is, and demonstrates.
Priority Queues Dr. David Matuszek
Pertemuan 24 DISCRETE-EVENT SYSTEM SIMULATION Matakuliah: D0174/ Pemodelan Sistem dan Simulasi Tahun: Tahun 2009.
CPSC1301 Computer Science 1 Chapter 12 Creating and Modifying Text part 4.
1 Building Java Programs Chapter 7: Arrays These lecture notes are copyright (C) Marty Stepp and Stuart Reges, They may not be rehosted, sold, or.
CSE373: Data Structures & Algorithms Lecture 6: Priority Queues Dan Grossman Fall 2013.
Hashing Hashing is another method for sorting and searching data.
CS 206 Introduction to Computer Science II 04 / 22 / 2009 Instructor: Michael Eckmann.
1 Heaps and Priority Queues v2 Starring: Min Heap Co-Starring: Max Heap.
UNIT 5.  The related activities of sorting, searching and merging are central to many computer applications.  Sorting and merging provide us with a.
Chapter 11Java: an Introduction to Computer Science & Programming - Walter Savitch 1 Chapter 11 l Basics of Recursion l Programming with Recursion Recursion.
CSE373: Data Structures & Algorithms Lecture 6: Priority Queues Kevin Quinn Fall 2015.
CreatingClasses-SlideShow-part31 Creating Classes part 3 Barb Ericson Georgia Institute of Technology Dec 2009.
Week 10 - Friday.  What did we talk about last time?  Graph representations  Adjacency matrix  Adjacency lists  Depth first search.
M1G Introduction to Programming 2 3. Creating Classes: Room and Item.
CS 106 Introduction to Computer Science I 03 / 02 / 2007 Instructor: Michael Eckmann.
ICS3U_FileIO.ppt File Input/Output (I/O)‏ ICS3U_FileIO.ppt File I/O Declare a file object File myFile = new File("billy.txt"); a file object whose name.
Finally! Making the Villagers CS1316: Representing Structure and Behavior.
HEAPS. Review: what are the requirements of the abstract data type: priority queue? Quick removal of item with highest priority (highest or lowest key.
Searching and Sorting Searching: Sequential, Binary Sorting: Selection, Insertion, Shell.
AVL Trees and Heaps. AVL Trees So far balancing the tree was done globally Basically every node was involved in the balance operation Tree balancing can.
Winter 2006CISC121 - Prof. McLeod1 Stuff No stuff today!
Week 15 – Wednesday.  What did we talk about last time?  Review up to Exam 1.
Lecture 8: Advanced OOP Part 2. Overview Review of Subtypes Interfaces Packages Sorting.
Introduction to Computer Programming - Project 2 Intro to Digital Technology.
Generalizing Simulations CS1316: Representing Structure and Behavior.
1. What is it? It is a queue that access elements according to their importance value. Eg. A person with broken back should be treated before a person.
Week 10 - Wednesday.  What did we talk about last time?  Method example  Roulette simulation  Types in Java.
Searching CSE 103 Lecture 20 Wednesday, October 16, 2002 prepared by Doug Hogan.
Queues CS 367 – Introduction to Data Structures. Queue A queue is a data structure that stores data in such a way that the last piece of data stored,
1 Stacks Abstract Data Types (ADTs) Stacks Application to the analysis of a time series Java implementation of a stack Interfaces and exceptions.
Stacks as an Abstract Data Type CS1316: Representing Structure and Behavior.
Georgia Institute of Technology More on Creating Classes Barb Ericson Georgia Institute of Technology June 2006.
CSE332: Data Abstractions Lecture 4: Priority Queues Dan Grossman Spring 2012.
Discrete Event Simulation
Review Array Array Elements Accessing array elements
CSC317 Selection problem q p r Randomized‐Select(A,p,r,i)
Creating and Modifying Text part 2
Stacks as an Abstract Data Type
Recursive Objects Singly Linked Lists.
LCC 6310 Computation as an Expressive Medium
slides created by Ethan Apter and Marty Stepp
Presentation transcript:

Problem Solving with Data Structures using Java: A Multimedia Approach Chapter 17: Discrete Event Simulation

Chapter Objectives

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 Already presented, but now used: 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: 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? The classic bell-shaped curve

Generating a uniform distribution import java.util.*; // Need this for Random import java.io.*; // For BufferedWriter public class GenerateUniform { public static void main(String[] args) { Random rng = new Random(); // Random Number Generator 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."); } // Fill it with 500 numbers between 0.0 and 1.0, uniformly distributed for (int i=0; i < 500; i++){ try{ output.write("\t"+rng.nextFloat()); 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");} } By writing out a tab and the integer, we don’t have to do the string conversion.

Generating a Histogram Now we have lots of numbers between 0 and 1. We want to count the number between 0.9 and 1.0, 0.8 and 0.9, 0.7 and 0.8, and so on. We need to count them into bins. Great job for a Map!

HistogramGenerator import java.util.*; import java.io.*; /** * Class to generate a histogram Mark Guzdial Barb Ericson */ public class HistogramGenerator { /** the map to hold the values */ private Map valueMap = new TreeMap (); For a given value (like 0.8), we want a count. That’s Double- >Integer map

/** * Method to read a set of values from the inputFile and create * bins based on the array of keys. This will count the number * of values in each bin. Any value larger than the last key * will be put in the last bin. inputFile the file to read from an array of key values to use */ public void countValuesForKeys(String inputFile, double[] keys) { BufferedReader reader = null; String line = null; double doubleValue = 0.0; boolean found = false; int lastIndex = keys.length - 1; // put the keys in the map using a count of 0 for (int i = 0; i < keys.length; i++) { valueMap.put(keys[i],0); }

try { // open the file reader = new BufferedReader(new FileReader(inputFile)); // loop reading from the file while ((line = reader.readLine()) != null) { doubleValue = Double.parseDouble(line); found = false; for (double key : keys) { if (doubleValue < key) { valueMap.put(key,valueMap.get(key) + 1); found = true; break; } if (!found) valueMap.put(keys[lastIndex], valueMap.get(keys[lastIndex]) + 1); } // close the file reader.close(); } catch (Exception ex) { System.out.println(ex.getMessage()); ex.printStackTrace(); } If the double value we read is less than this key, increment the count at that key

/** * Method to read a set of values from the inputFile create even * bins based on the passed factor. This will count the number * of values in each bin. inputFile the file to read from factor the factor to use to break the values into bins */ public void countValues(String inputFile, int factor) { BufferedReader reader = null; String line = null; double doubleValue = 0.0; double key = 0.0; int currCount = 0; try { // open the file reader = new BufferedReader(new FileReader(inputFile));

// loop reading from the file while ((line = reader.readLine()) != null) { doubleValue = Double.parseDouble(line); doubleValue = doubleValue * factor; key = Math.ceil(doubleValue) / (double) factor; if (valueMap.containsKey(key)) { currCount = valueMap.get(key); currCount++; valueMap.put(key,currCount); } else { valueMap.put(key,1); } // close the file reader.close(); } catch (Exception ex) { System.out.println(ex.getMessage()); ex.printStackTrace(); }

Now, write the counts to a file for graphing /** * Method to output the keys and values in the histogram * to a file fileName the name of the file to write to */ public void writeFile(String fileName) { BufferedWriter writer = null; double key = 0; int value = 0; Set keySet = null;

try { // create the writer writer = new BufferedWriter(new FileWriter(fileName)); // get the keys and loop through them keySet = valueMap.keySet(); Iterator iterator = keySet.iterator(); while (iterator.hasNext()) { key = iterator.next(); value = valueMap.get(key); writer.write(key + "\t" + value); writer.newLine(); } // close the writer writer.close(); } catch (Exception ex) { System.out.println(ex.getMessage()); ex.printStackTrace(); }

Using it /** * Generate the histogram from the uniform data */ public static void genUniform() { HistogramGenerator histGen = new HistogramGenerator(); double[] keyArray = {0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0}; histGen.countValuesForKeys("C:/dsBook/uniform.txt",keyArray); histGen.writeFile("C:/dsBook/uniformHist.txt"); } /** * Method to generate the normal histogram */ public static void genNormal() { HistogramGenerator histGen = new HistogramGenerator(); double[] keyArray = {-1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1,0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0}; histGen.countValuesForKeys("C:/dsBook/normal.txt",keyArray); histGen.writeFile("C:/dsBook/normalHist.txt"); }

How do we view a distribution? A Histogram

Load the values into a Spreadsheet, Then graph the result A uniform distribution

A Uniform Distribution

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

Again, in a Spreadsheet

Graphing the normal distribution The end aren’t actually high— the tails go further.

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

Key idea: Ordering Events by 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.

Exercising an EventQueue public class EventQueueExercisor { public static void main(String[] args){ // Make an EventQueue EventQueue queue = new EventQueue(); // Now, stuff it full of events, out of order. SimEvent event = new SimEvent(); event.setTime(5.0); queue.add(event); event = new SimEvent(); event.setTime(2.0); queue.add(event); 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()); } We’re stuffing the EventQueue with events whose times are out of order.

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 2 ) in the worst case, but on 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 Sort public void sort() { // For comparing to elements at smaller indices SimEvent considered = null; SimEvent compareEvent = null; // Just for use in loop // Smaller index we're comparing to int compare; // Start out assuming that position 0 is "sorted" // When position==1, compare elements at indices 0 and 1 // When position==2, compare at indices 0, 1, and 2, etc. for (int position=1; position < elements.size(); position++) { considered = (SimEvent) elements.get(position); // Now, we look at "considered" versus the elements // less than "compare" compare = position;

// While the considered event is greater than the compared event, // it's in the wrong place, so move the elements up one. compareEvent = (SimEvent) elements.get(compare-1); while (compareEvent.getTime() > considered.getTime()) { elements.set(compare,elements.get(compare-1)); compare = compare-1; // If we get to the end of the array, stop if (compare <= 0) { break; } // else get ready for the next time through the loop else { compareEvent = (SimEvent) elements.get(compare-1); } // Wherever we stopped, this is where "considered" belongs elements.set(compare,considered); } // for all positions 1 to the end } // end of sort()

Sorting is expensive It takes a lot of time to re-sort the event queue each time. Better option: Put each new event in the right place as it enters the queue.

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

insertInOrder() /** * Put thisEvent into elements, assuming * that it's already in order. **/ public void insertInOrder(SimEvent thisEvent){ SimEvent comparison = null; // Have we inserted yet? boolean inserted = false; for (int i=0; i < elements.size(); i++){ comparison = (SimEvent) elements.get(i);

// Assume elements from 0..i are less than thisEvent // If the element time is GREATER, insert here and // shift the rest down if (thisEvent.getTime() < comparison.getTime()) { //Insert it here inserted = true; elements.add(i,thisEvent); break; // We can stop the search loop } } // 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);} }

Option #3: Min-Heap So, we don’t really need to sort or insert in order. The critical thing is that each pop() gives us the smallest time. A min-heap is a kind of binary tree that is complete and where the value at each node is less than or equal to the values stored in the children nodes. A complete binary tree has all nodes filled except the last (bottom/deepest) level, and the bottom is filled left-to-right.

Example Min-Heap The top value here (the 5) is guaranteed to be the lowest value

Adding a “3” Add 3 to right But can’t have 3 below 10! And can’t have 5 above 3 Final version!

Java’s PriorityQueue does this! The Java class PriorityQueue already implements a min-heap. Our third option is just to use the PriorityQueue for the EventQueue. But now you know what the options are and how they work.

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: Distributor: 0 Arrived at warehouse Time: Distributor: 0 is blocking >>> Timestep: 1 Time: Distributor: 3 Arrived at warehouse Time: Distributor: 3 is blocking >>> Timestep: 1 Time: Distributor: 4 Arrived at warehouse Time: Distributor: 4 is blocking >>> Timestep: 1 Time: Distributor: 2 Arrived at warehouse Time: Distributor: 2 is blocking >>> Timestep: 1 Time: Distributor: 1 Arrived at warehouse Time: Distributor: 1 is blocking >>> Timestep: 3 Time: Truck: 2 Arrived at warehouse with load 13 Time: Distributor: 0 unblocked! Time: Distributor: 0 Gathered product for orders of 11 >>> Timestep: 3 Time: Truck: 0 Arrived at warehouse with load 18 Time: Distributor: 3 unblocked! Time: Distributor: 3 Gathered product for orders of 12 >>> Timestep: 3 Time: Distributor: 0 Arrived at market >>> Timestep: 4 Time: Truck: 1 Arrived at warehouse with load 20 Time: Distributor: 4 unblocked! Time: Distributor: 4 Gathered product for orders of 19 Notice that time 2 never occurs!

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

FactorySimulation: Extend a few classes

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 now = topEvent.getTime(); // Let the agent now that its event has occurred topAgent = topEvent.getAgent(); topAgent.processEvent(topEvent.getMessage()); // repaint the world to show the movement // IF there is a world if (world != null) { world.repaint();} // Do the end of step processing this.endStep((int) now); } As long as there are events in the queue, and we’re not at the stopTime: Grab an event. Make it’s time “now” Process the event.

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 * market **/ public class SimEvent{ /// Fields /// /** When does this event occur? */ public double time; /** 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; It’s a time, an Agent, and an integer that the Agent will understand as a 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 this.setBodyColor(Color.green); // Let green deliver! // Show the truck at the factory this.moveTo(30,350); // Load up at the factory, and set off for the warehouse load = this.newLoad(); ((DESimulation) thisSim).addEvent( new SimEvent(this,tripTime(),WAREHOUSE_ARRIVE)); } The truck gets a load, then schedules itself to arrive at the Warehouse.

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! 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.

Thin-line between data and program What happens in a computation is about an interaction between the program and the data. Sometimes the data ‘tells’ the computer what to do, like the operations in the branches of the scene graph. Just seeing the source code doesn’t tell you what’s going to happen. Data is important, and data can specify behavior.