diff --git a/.gitignore b/.gitignore
index 524f096..04a0844 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,7 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
+
+
+# mine
+pdf/*
\ No newline at end of file
diff --git a/SimulatoreBCNN/SimulatoreBCNN.iml b/SimulatoreBCNN/SimulatoreBCNN.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/SimulatoreBCNN/SimulatoreBCNN.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SimulatoreBCNN/src/Sim.java b/SimulatoreBCNN/src/Sim.java
new file mode 100644
index 0000000..fc19159
--- /dev/null
+++ b/SimulatoreBCNN/src/Sim.java
@@ -0,0 +1,149 @@
+import SimUtils.*;
+import SimUtils.Queue;
+
+import java.util.*;
+class Sim {
+
+ // Class Sim variables
+ public static double Clock, MeanInterArrivalTime, MeanServiceTime, SIGMA, LastEventTime,
+ TotalBusy, MaxQueueLength, SumResponseTime;
+ public static long NumberOfCustomers, QueueLength, NumberInService,
+ TotalCustomers, NumberOfDepartures, LongService;
+
+ public final static int arrival = 1;
+ public final static int departure = 2;
+
+ public static EventList FutureEventList;
+ public static Queue Customers;
+ public static Random stream;
+
+ public static void main(String argv[]) {
+
+ MeanInterArrivalTime = 4.5; MeanServiceTime = 3.2;
+ SIGMA = 0.6; TotalCustomers = 1000;
+ long seed = Long.parseLong(argv[0]);
+
+ stream = new Random(seed); // initialize rng stream
+ FutureEventList = new EventList();
+ Customers = new Queue();
+
+ Initialization();
+
+ // Loop until first "TotalCustomers" have departed
+ while(NumberOfDepartures < TotalCustomers ) {
+ Event evt = (Event)FutureEventList.getMin(); // get imminent event
+ FutureEventList.dequeue(); // be rid of it
+ Clock = evt.get_time(); // advance simulation time
+ if( evt.get_type() == arrival ) ProcessArrival(evt);
+ else ProcessDeparture(evt);
+ }
+ ReportGeneration();
+ }
+
+ // seed the event list with TotalCustomers arrivals
+ public static void Initialization() {
+ Clock = 0.0;
+ QueueLength = 0;
+ NumberInService = 0;
+ LastEventTime = 0.0;
+ TotalBusy = 0 ;
+ MaxQueueLength = 0;
+ SumResponseTime = 0;
+ NumberOfDepartures = 0;
+ LongService = 0;
+
+ // create first arrival event
+ Event evt = new Event(arrival, exponential( stream, MeanInterArrivalTime));
+ FutureEventList.enqueue( evt );
+ }
+
+ public static void ProcessArrival(Event evt) {
+ Customers.enqueue(evt);
+ QueueLength++;
+ // if the server is idle, fetch the event, do statistics
+ // and put into service
+ if( NumberInService == 0) ScheduleDeparture();
+ else TotalBusy += (Clock - LastEventTime); // server is busy
+
+ // adjust max queue length statistics
+ if (MaxQueueLength < QueueLength) MaxQueueLength = QueueLength;
+
+ // schedule the next arrival
+ Event next_arrival = new Event(arrival, Clock+exponential(stream, MeanInterArrivalTime));
+ FutureEventList.enqueue( next_arrival );
+ LastEventTime = Clock;
+ }
+
+ public static void ScheduleDeparture() {
+ double ServiceTime;
+ // get the job at the head of the queue
+ while (( ServiceTime = normal(stream, MeanServiceTime, SIGMA)) < 0 );
+ Event depart = new Event(departure,Clock+ServiceTime);
+ FutureEventList.enqueue( depart );
+ NumberInService = 1;
+ QueueLength--;
+ }
+
+ public static void ProcessDeparture(Event e) {
+ // get the customer description
+ Event finished = (Event) Customers.dequeue();
+ // if there are customers in the queue then schedule
+ // the departure of the next one
+ if( QueueLength > 0 ) ScheduleDeparture();
+ else NumberInService = 0;
+ // measure the response time and add to the sum
+ double response = (Clock - finished.get_time());
+ SumResponseTime += response;
+ if( response > 4.0 ) LongService++; // record long service
+ TotalBusy += (Clock - LastEventTime );
+ NumberOfDepartures++;
+ LastEventTime = Clock;
+ }
+
+ public static void ReportGeneration() {
+ double RHO = TotalBusy/Clock;
+ double AVGR = SumResponseTime/TotalCustomers;
+ double PC4 = ((double)LongService)/TotalCustomers;
+
+
+ System.out.println( "SINGLE SERVER QUEUE SIMULATION - GROCERY STORE CHECKOUT COUNTER ");
+ System.out.println( "\tMEAN INTERARRIVAL TIME "
+ + MeanInterArrivalTime );
+ System.out.println( "\tMEAN SERVICE TIME "
+ + MeanServiceTime );
+ System.out.println( "\tSTANDARD DEVIATION OF SERVICE TIMES " + SIGMA );
+ System.out.println( "\tNUMBER OF CUSTOMERS SERVED " + TotalCustomers );
+ System.out.println();
+ System.out.println( "\tSERVER UTILIZATION " + RHO );
+ System.out.println( "\tMAXIMUM LINE LENGTH " + MaxQueueLength );
+ System.out.println( "\tAVERAGE RESPONSE TIME " + AVGR + " MINUTES" );
+ System.out.println( "\tPROPORTION WHO SPEND FOUR ");
+ System.out.println( "\t MINUTES OR MORE IN SYSTEM " + PC4 );
+ System.out.println( "\tSIMULATION RUNLENGTH " + Clock + " MINUTES" );
+ System.out.println( "\tNUMBER OF DEPARTURES " + TotalCustomers );
+ }
+
+ public static double exponential(Random rng, double mean) {
+ return -mean*Math.log( rng.nextDouble() );
+ }
+
+ public static double SaveNormal;
+ public static int NumNormals = 0;
+ public static final double PI = 3.1415927 ;
+
+ public static double normal(Random rng, double mean, double sigma) {
+ double ReturnNormal;
+ // should we generate two normals?
+ if(NumNormals == 0 ) {
+ double r1 = rng.nextDouble();
+ double r2 = rng.nextDouble();
+ ReturnNormal = Math.sqrt(-2*Math.log(r1))*Math.cos(2*PI*r2);
+ SaveNormal = Math.sqrt(-2*Math.log(r1))*Math.sin(2*PI*r2);
+ NumNormals = 1;
+ } else {
+ NumNormals = 0;
+ ReturnNormal = SaveNormal;
+ }
+ return ReturnNormal*sigma + mean ;
+ }
+}
\ No newline at end of file
diff --git a/SimulatoreBCNN/src/SimUtils/Event.java b/SimulatoreBCNN/src/SimUtils/Event.java
new file mode 100644
index 0000000..113ccbb
--- /dev/null
+++ b/SimulatoreBCNN/src/SimUtils/Event.java
@@ -0,0 +1,21 @@
+package SimUtils;
+
+public class Event implements Comparable {
+
+ public Event(int a_type, double a_time) { _type = a_type; time = a_time; }
+
+ public double time;
+ private int _type;
+
+ public int get_type() { return _type; }
+ public double get_time() { return time; }
+
+ public Event leftlink, rightlink, uplink;
+
+ public int compareTo(Object _cmpEvent ) {
+ double _cmp_time = ((Event) _cmpEvent).get_time() ;
+ if( this.time < _cmp_time) return -1;
+ if( this.time == _cmp_time) return 0;
+ return 1;
+ }
+}
diff --git a/SimulatoreBCNN/src/SimUtils/EventList.java b/SimulatoreBCNN/src/SimUtils/EventList.java
new file mode 100644
index 0000000..448e65b
--- /dev/null
+++ b/SimulatoreBCNN/src/SimUtils/EventList.java
@@ -0,0 +1,195 @@
+package SimUtils;
+
+// EventList is implemented as a splay tree
+// v1. class Event knows this and has fields
+// leftlink, rightlink, uplink
+public class EventList {
+ Event root;
+ Event update_p;
+ Event left,right,next,temp,farleft,farfarleft;
+ double ntime;
+ boolean update_code;
+ int size = 0;
+ Object owner;
+
+ public EventList(){ }
+
+ public String toString(){
+ return "EventList ";
+ }
+
+ public boolean isEmpty(){
+ return (this.root == null);
+ }
+
+ public void enqueue(Event n){
+ size++;
+ n.uplink = null;
+ next = this.root;
+ this.root = n;
+ if (next == null){
+ n.leftlink = null;
+ n.rightlink = null;
+ }
+ else{
+ mainblock: {
+ ntime = n.time;
+ left = n;
+ right = n;
+ if (next.time > ntime){
+ //2222222222222222222222222
+ do{
+ temp = next.leftlink;
+ if (temp == null){
+ right.leftlink = next;
+ next.uplink = right;
+ left.rightlink = null;
+ break mainblock;
+ }
+ if (temp.time <= ntime){
+ right.leftlink = next;
+ next.uplink = right;
+ right = next;
+ next = temp;
+ break;
+ }
+ next.leftlink = temp.rightlink;
+ if (temp.rightlink != null)
+ temp.rightlink.uplink = next;
+ right.leftlink = temp;
+ temp.uplink = right;
+ temp.rightlink = next;
+ next.uplink = temp;
+ right = temp;
+ next = temp.leftlink;
+ if (next == null){
+ left.rightlink = null;
+ break mainblock;
+ }
+ }while (next.time > ntime);
+ }
+ forblock:
+ for( ; ; ){
+ //111111111111111111111111111
+ do{
+ temp = next.rightlink;
+ if (temp == null){
+ left.rightlink = next;
+ next.uplink = left;
+ right.leftlink = null;
+ break forblock;
+ }
+ if (temp.time > ntime){
+ left.rightlink = next;
+ next.uplink = left;
+ left = next;
+ next = temp;
+ break;
+ }
+ next.rightlink = temp.leftlink;
+ if (temp.leftlink!=null)
+ temp.leftlink.uplink = next;
+ left.rightlink = temp;
+ temp.uplink = left;
+ temp.leftlink = next;
+ next.uplink = temp;
+ left = temp;
+ next = temp.rightlink;
+ if (next == null){
+ right.leftlink = null;
+ break forblock;
+ }
+ }while (next.time <= ntime);
+
+ //2222222222222222222222222222
+ do{
+ temp = next.leftlink;
+ if (temp == null){
+ right.leftlink = next;
+ next.uplink = right;
+ left.rightlink = null;
+ break forblock;
+ }
+ if (temp.time <= ntime){
+ right.leftlink = next;
+ next.uplink = right;
+ right = next;
+ next = temp;
+ break;
+ }
+ next.leftlink = temp.rightlink;
+ if (temp.rightlink != null)
+ temp.rightlink.uplink = next;
+ right.leftlink = temp;
+ temp.uplink = right;
+ temp.rightlink = next;
+ next.uplink = temp;
+ right = temp;
+ next = temp.leftlink;
+ if (next == null){
+ left.rightlink = null;
+ break forblock;
+ }
+ }while (next.time > ntime);
+ }
+ }
+
+ //99999999999999999999999999999
+ temp = n.leftlink;
+ n.leftlink = n.rightlink;
+ n.rightlink = temp;
+ }
+ }
+ public Event getMin(){
+
+ //assumed that the tree is not empty
+ next = this.root;
+ left = next.leftlink;
+ if (left ==null){
+ update_code = true;
+ return next;
+ }
+ else{
+ for ( ; ; ){
+ farleft = left.leftlink;
+ if (farleft == null){
+ update_code = false;
+ update_p = next;
+ return left;
+ }
+ farfarleft = farleft.leftlink;
+ if (farfarleft==null){
+ update_code = false;
+ update_p = left;
+ return farleft;
+ }
+ next.leftlink = farleft;
+ farleft.uplink = next;
+ left.leftlink = farleft.rightlink;
+ if (farleft.rightlink!=null)
+ farleft.rightlink.uplink = left;
+ farleft.rightlink = left;
+ left.uplink = farleft;
+ next = farleft;
+ left = farfarleft;
+ }
+ }
+ }
+
+ public void dequeue(){
+ size--;
+ //assumed that getMin has been the last splay tree operation invoked. Removes that element.
+ if (update_code){
+ next = null; //remove pointer to the returned Event
+ root = root.rightlink;
+ if (root!=null)
+ root.uplink = null;
+ }
+ else{
+ left = farleft = null; //remove pointers to the returned event
+ if (update_p.leftlink.rightlink!=null)
+ update_p.leftlink.rightlink.uplink = update_p;
+ update_p.leftlink = update_p.leftlink.rightlink;
+ }
+ }
+}
diff --git a/SimulatoreBCNN/src/SimUtils/Queue.java b/SimulatoreBCNN/src/SimUtils/Queue.java
new file mode 100644
index 0000000..32f0f07
--- /dev/null
+++ b/SimulatoreBCNN/src/SimUtils/Queue.java
@@ -0,0 +1,253 @@
+package SimUtils;
+
+/**
+
+ This class provides a fairly efficient implementation of a FIFO
+ queue. We use an array to implement the queue which is
+ automatically increased in size when necessary. Note that the queue
+ is never shrunk in the current implementation.
+
+ @author Mark Astley
+ @version $Revision: 1.5 $ ($Date: 1998/09/07 23:00:37 $)
+
+ */
+
+// public class Queue implements Cloneable, Serializable {
+public class Queue {
+ /**
+ This constant sets the initial size of a queue when the default
+ constructor is invoked to create a queue. Users requiring a
+ different initial size may invoke the appropriate constructor
+ below.
+ */
+ public static final int INITIAL_SIZE = 10;
+
+ /**
+ This array holds the queue. We use a dynamically growing circular
+ array to represent the queue. Queue size is doubled when
+ necessary which should make for a rather efficient implementation.
+ */
+ Object[] theQ;
+
+ /**
+ These two fields hold indices to the first and last element of the
+ queue respectively. Technically, back points to the
+ first open spot in the queue rather than the last element.
+ */
+ int front;
+ int back;
+
+ /**
+ Default constructor for the Queue class.
+ */
+ public Queue() {
+ theQ = new Object[INITIAL_SIZE];
+ front=back=0;
+ }
+
+ /**
+ Alternative constructor for the Queue class which allows
+ the specification of the initial size of the queue.
+
+ @param initialSize The initial size of the new Queue.
+ */
+ public Queue(int initialSize) {
+ theQ = new Object[initialSize];
+ front=back=0;
+ }
+
+ /**
+ This private method is used to double the size of the queue when
+ more space is required (as a result of calling enqueue). Note
+ that because the implementation is in terms of a circular array,
+ we have to be careful when copying elements from the old array to
+ the new array.
+ */
+ synchronized private void grow() {
+ Object[] newQ = new Object[2 * theQ.length];
+
+ if (back >= front)
+ System.arraycopy(theQ, front, newQ, front, back - front + 1);
+ else {
+ System.arraycopy(theQ, front, newQ, front, theQ.length - front);
+ System.arraycopy(theQ, 0, newQ, theQ.length, back);
+ back = front + theQ.length - 1;
+ }
+
+ theQ = newQ;
+ }
+
+ /**
+ Determine if the queue is empty.
+
+ @return true if the queue contains no elements,
+ false otherwise.
+ */
+ synchronized public boolean empty() {
+ return (front == back);
+ }
+
+ /**
+ Add an object to the end of the queue.
+
+ @param q A reference to the object to add.
+ @return void
+ */
+ synchronized public void enqueue(Object q) {
+ if (((back + 1) % theQ.length) == front)
+ grow();
+
+ theQ[back] = q;
+ back = (back + 1) % theQ.length;
+ }
+
+ /**
+ Remove an object from the front of the queue. The returned object
+ is removed from the queue.
+
+ @return A reference to the Object at the front of the
+ queue. Returns null if the queue is empty.
+ */
+ synchronized public Object dequeue() {
+ Object toReturn = null;
+
+ if (!empty()) {
+ toReturn = theQ[front];
+ front = (front + 1) % theQ.length;
+ }
+
+ return toReturn;
+ }
+
+ /**
+ Get the object at the front of the queue without removing it.
+
+ @return A reference to the Object at the front of the
+ queue.
+ */
+ synchronized public Object peekFront() {
+ if (!empty())
+ return theQ[front];
+ else
+ return null;
+ }
+
+ /**
+ Determine how many objects are currently stored in the queue.
+
+ @return An int indicating the number of objects in the
+ queue.
+ */
+ synchronized public int numElements() {
+ if (front <= back)
+ return (back - front);
+ else
+ return (back + (theQ.length - front));
+ }
+
+
+ /**
+ This function allows arbitrary queue elements to be removed.
+ Elements which are equal (according to the equal
+ function) to the argument are removed from the queue. Note that
+ this version of the function only removes the FIRST element
+ found. Use the removeAll function to remove ALL elements
+ equal to the argument.
+
+ @param rem The object to be removed from the queue.
+ @return true if an element was removed, false
+ otherwise.
+ */
+ synchronized public boolean remove(Object rem) {
+ int i, x, y;
+
+ // PRAGMA [debug,osl.util.Queue] Log.println(" Searching for element: " + rem);
+ // First track down the element to remove (if there is one)
+ for(i=front; i != back; i = (i + 1) % theQ.length)
+ if (rem.equals(theQ[i]))
+ break;
+
+ // If nothing found then return false...
+ if (i == back)
+ // PRAGMA [debug,osl.util.Queue] {
+ // PRAGMA [debug,osl.util.Queue] Log.println(" Element not found, returning");
+ return false;
+ // PRAGMA [debug,osl.util.Queue] } else {
+ // PRAGMA [debug,osl.util.Queue] Log.println(" Element found at position: " + i);
+ // PRAGMA [debug,osl.util.Queue] }
+
+ // Otherwise remove the one element. This is a bit of a hack but
+ // should be fairly efficient.
+ Object[] newQ = new Object[theQ.length];
+ for(x=front, y=0; x != back; x = (x + 1) % theQ.length)
+ if (x != i) {
+ newQ[y] = theQ[x];
+ y++;
+ }
+
+ theQ = newQ;
+ front = 0;
+ back = y;
+
+ return true;
+ }
+
+ /**
+ This function has the same behavior as remove except that
+ ALL matching elements are removed from the queue.
+
+ @param rem The object to be removed from the queue.
+ @return The number of elements removed.
+ */
+ synchronized public int removeAll(Object rem) {
+ int i, match, x, y, z;
+
+ // Track down all the elements to remove.
+ int[] toRemove = new int[numElements()];
+ for(i=front, match=0; i != back; i = (i + 1) % theQ.length)
+ if (rem.equals(theQ[i])) {
+ toRemove[match] = i;
+ match++;
+ }
+
+ // See if anything matched, if not then just return
+ if (match == 0)
+ return 0;
+
+ // Now make a new array with all the matching elements removed
+ Object[] newQ = new Object[theQ.length];
+ for(x=front, y=0, z=0; x != back; x = (x + 1) % theQ.length)
+ if (z < match)
+ if (x != toRemove[z]) {
+ newQ[y] = theQ[x];
+ y++;
+ } else
+ z++;
+ else {
+ newQ[y] = theQ[x];
+ y++;
+ }
+
+ theQ = newQ;
+ front = 0;
+ back = y;
+
+ // match holds the number of things we removed
+ return match;
+ }
+
+ /**
+ The canonical toString method.
+ */
+ synchronized public String toString() {
+ String returnVal = "Queue: ";
+
+ if (empty())
+ return returnVal + "no elements";
+
+ for(int i=front; i != back; i = (i + 1) % theQ.length)
+ returnVal = returnVal + theQ[i].toString() + " ";
+
+ return returnVal;
+ }
+}
diff --git a/pdf/README.txt b/pdf/README.txt
new file mode 100644
index 0000000..984971e
--- /dev/null
+++ b/pdf/README.txt
@@ -0,0 +1,13 @@
+Il file SimulatoreJava-BCNNcapitolo4.zip contiene il simulatore presentato nel capitolo 4 del libro di testo
+
+Il file SimulatoreBCNNintelliJ.zip contiene un export da IntelliJ IDEA dello stesso simulatore;
+unica differenza: le classi di utilità generale sono contenute in un package "SimUtils"
+
+Il file QueueingTools.xls contiene vari fogli di calcolo che implementano il calcolo dei principali indici
+di prestazione per alcune categorie di modelli costituiti da una sola coda (si veda il capitolo 6 del libro di testo).
+Per esempio un foglio è dedicato alla M/M/c mentre un altro foglio è dedicato alla M/G/1.
+Potete usare questi fogli di calcolo per confrontare i risultati ottenuti con il simulatore e quelli ricavati dalle formule
+dei fogli excel, come strumento di verifica del buon funzionamento del simulatore.
+
+Potete anche confrontare i risultati ottenuti con questo simulatore e quelli ottenuti con JMT (Java Modelling Tools), a parità
+di parametri e di distribuzione dei tempi di interarrivo e di servizio.
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..15cf713
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,16 @@
+
+
+ 4.0.0
+
+ net.berack
+ valpre
+ 1.0-SNAPSHOT
+
+
+ 23
+ 23
+
+
+
\ No newline at end of file