= 1.4.
Finally, the replacement time is uniformly distributed between 0.1 and
0.12. We are interested in statistics of the lifetime of the system as
a whole.
We wrote the following program. It consists of the entities job,
server and breakdown, the priority queue q, the
resource shop and the various generator, histogram and analysis objects.
#include <sim/sim.h>
// phases job
enum {ARRIVAL,DEPARTURE,INTERRUPTED};
// phases server
enum {RUNNING,BROKEN};
// phases breakdown
enum {BOTH_SERVERS_OK,ONE_SERVER_DOWN,BOTH_SERVERS_DOWN};
// number of job types,number of grades of service and number of runs
enum {JOBTYPES=3,PRIORITIES=4,RUNS=10000};
// define highest queuingpriority and maximal waiting time
enum {HIGHEST=3,MAXWAITED=50};
class server;
simulation* sim;
histogram* waited[PRIORITIES];
histogram* total[PRIORITIES];
histogram* interrupted[PRIORITIES];
histogram* lost;
histogram* lifetime;
histogram* prob;
generator* g1, *g2;
resource* shop;
queue* q;
server* s;
double mean[JOBTYPES] = {0.76,2.14,13.65};
double stddev[JOBTYPES] = {0.16,0.22,1.83};
double probability[JOBTYPES] = {0.21,0.57,0.22};
double arrivalrate[PRIORITIES] = {19.8,13.6,11.2,27.5};
class job : public entity
{
public :
job(int ph,int qp,int sp=0);
virtual int operator()();
int arrival();
int departure();
double servicetime();
double startingtime;
double timeleft;
int interrupts;
};
class server : public entity
{
public :
server(int ph);
virtual int operator()();
int serve();
int preempt();
int discard();
void breakdown(double t);
void fixed();
job* current;
};
class breakdown : public entity
{
private :
int runs;
double last;
public :
breakdown(int ph,int sp);
virtual int operator()();
int bothok();
int onedown();
int bothdown();
};
// constructor, taking phase, scheduling priority and queuing
// priority of the job
job::job(int ph,int qp,int sp) : entity(ph,qp,sp)
{
startingtime = 0;
timeleft = 0;
interrupts = 0;
}
// behavior of a job
int job::operator()()
{
switch (phase())
{
case ARRIVAL :
return arrival();
case DEPARTURE :
return departure();
}
return FALSE;
}
// arrival event
int job::arrival()
{
job* j;
// add time stamp (for check on waiting time)
stamp();
// schedule next job
j = new job(ARRIVAL,queuingpriority());
sim -> schedule(j,(g1 -> exponential(arrivalrate[queuingpriority()])));
// append and report.
report(total[queuingpriority()]);
q -> append(this);
return OK;
}
// departure event
int job::departure()
{
// add sample, release shop and leave it
interrupted[queuingpriority()] -> sample(interrupts);
shop -> release();
sim -> terminate(this);
s -> current = NULL;
return OK;
}
// if interrupted return time left, else determine service time
double job::servicetime()
{
double p;
if (phase() == INTERRUPTED)
return timeleft;
else
{
p = g1 -> uniform(0,1);
if (p < probability[0])
return (g1 -> normal(mean[0],stddev[0]));
else if (p < (probability[0] + probability[1]))
return (g1 -> normal(mean[1],stddev[1]));
else
return (g1 -> normal(mean[2],stddev[2]));
}
}
server::server(int ph) : entity(ph)
{
current = NULL;
}
// if possible serve or preempt
int server::operator()()
{
job* j;
// check if broken
if (phase() == BROKEN)
return FALSE;
// check if empty
if (!(q -> empty()))
{
j = (job *)q -> front();
// if waited too long don't serve it
if ((j -> timespent()) > MAXWAITED)
return discard();
// shop available
else if (shop -> available())
return serve();
// current has not highest priority and the front has
else if ( (j -> queuingpriority() == HIGHEST) &&
(current -> queuingpriority() != HIGHEST) )
return preempt();
}
return FALSE;
}
// serve the front
int server::serve()
{
double t;
job* j;
j = (job *)q -> removefront();
// determine service time, before adjusting the phase
t = j -> servicetime();
// acquire shop and schedule departure
shop -> acquire();
j -> phase(DEPARTURE);
// set starting time and time left.
j -> startingtime = sim -> clock();
j -> timeleft = t;
// set current
current = j;
sim -> schedule(j,t);
return OK;
}
// preempt current job and serve the front
int server::preempt()
{
double t;
job* j;
j = (job *)q -> removefront();
// update current job, (it always exists)
current -> timeleft -= sim -> clock() - current -> startingtime;
current -> startingtime = sim -> clock();
// remove as departing entity and append as interrupted entity
sim -> passivate(current);
current -> phase(INTERRUPTED);
(current -> interrupts)++;
q -> append(current);
// update current job, (it always exists)
// serve new job
j -> phase(DEPARTURE);
t = j -> servicetime();
// set starting time and time left.
j -> startingtime = sim -> clock();
j -> timeleft = t;
current = j;
sim -> schedule(j,t);
return OK;
}
// discard front
int server::discard()
{
job* j;
j = (job *)q -> front();
// add sample
lost -> sample(j -> queuingpriority());
interrupted[queuingpriority()] -> sample(j -> interrupts);
// terminate without recording the waiting time
q -> terminatefront();
return FALSE;
}
// model a breakdown of the server
void server::breakdown(double t)
{
if (current)
{
// extract departure
sim -> passivate(current);
// update current job
current -> timeleft -= sim -> clock() - current -> startingtime;
current -> startingtime = sim -> clock() + t;
// schedule departure
sim -> schedule(current,(current -> timeleft + t));
}
phase(BROKEN);
}
// the server is fixed
void server::fixed()
{
phase(RUNNING);
}
breakdown::breakdown(int ph,int sp) : entity(ph,0,sp)
{
last = 0;
runs = 0;
}
// behavior of a breakdown
int breakdown::operator()()
{
switch (phase())
{
case BOTH_SERVERS_OK :
return bothok();
case ONE_SERVER_DOWN :
return onedown();
case BOTH_SERVERS_DOWN :
return bothdown();
}
return FALSE;
}
// both servers OK
int breakdown::bothok()
{
double life;
// if total number of runs is reached, quit
if (runs == RUNS)
sim -> quit();
else
runs++;
// schedule one part down
s -> fixed();
life = g2 -> weibull(1,1.4);
phase(ONE_SERVER_DOWN);
sim -> wait(life);
return OK;
}
// one server DOWN
int breakdown::onedown()
{
double life,replacementtime;
// schedule both parts down, if not replaced on time
life = g2 -> weibull(1,1.4);
replacementtime = g2 -> uniform(0.1,0.12);
if (life < replacementtime)
phase(BOTH_SERVERS_DOWN);
sim -> wait(life);
return OK;
}
// both servers DOWN
int breakdown::bothdown()
{
double replacementtime,t;
int j=0;
// replace both servers and adjust server process
replacementtime = g2 -> uniform(0.1,0.12);
phase(BOTH_SERVERS_OK);
sim -> wait(replacementtime);
s -> breakdown(replacementtime);
// sample time server was up, and the probability of the lifetime
t = sim -> clock() - last;
last = sim -> clock() + replacementtime;
lifetime -> sample(t);
while (j < t)
{
prob -> sample(j,1.0/RUNS);
j += 5;
}
return OK;
}
// initialize and run the simulation
void main()
{
analysis* alifetime;
analysis* aprob;
int i;
job* j;
breakdown* b;
sim = new simulation();
sim -> scan();
g1 = new generator(821); // inter-arrival and service times
g2 = new generator(18); // life and replacement times of the server
waited[0]= new histogram(0,1,20,FREQUENCY,STATISTICS,"waiting times for a
customer with queuingpriority 0");
waited[1]= new histogram(0,1,20,FREQUENCY,STATISTICS,"waiting times for a
customer with queuingpriority 1");
waited[2]= new histogram(0,1,20,FREQUENCY,STATISTICS,"waiting times for a
customer with queuingpriority 2");
waited[3]= new histogram(0,1,20,FREQUENCY,STATISTICS,"waiting times for a
customer with queuingpriority 3");
total[0]= new histogram(0,1,20,FREQUENCY,STATISTICS,"total time spent for a
customer with queuingpriority 0");
total[1]= new histogram(0,1,20,FREQUENCY,STATISTICS,"total time spent for a
customer with queuingpriority 1");
total[2]= new histogram(0,1,20,FREQUENCY,STATISTICS,"total time spent for a
customer with queuingpriority 2");
total[3]= new histogram(0,1,20,FREQUENCY,STATISTICS,"total time spent for a
customer with queuingpriority 3");
interrupted[0]= new histogram(0,1,20,FREQUENCY,STATISTICS,"number of
interrupts for a customer with queuingpriority 0");
interrupted[1]= new histogram(0,1,20,FREQUENCY,STATISTICS,"number of
interrupts for a customer with queuingpriority 1");
interrupted[2]= new histogram(0,1,20,FREQUENCY,STATISTICS,"number of
interrupts for a customer with queuingpriority 2");
interrupted[3]= new histogram(0,1,20,FREQUENCY,STATISTICS,"number of
interrupts for a customer with queuingpriority 3");
lost = new histogram(0,1,4,FREQUENCY,BARSGRAPH,"lost jobs");
lifetime = new histogram(0,10,20,FREQUENCY,GRAPH,"life time");
prob = new histogram(0,5,20,FREQUENCY,BARSGRAPH,"P(X > t)");
q = new queue();
shop = new resource(1);
// add reports on the waiting times
for (i=0;i reportwaiting(waited[i],0,i);
// initially the jobs are submitted and the server is conditional
// the first ones are scheduled in priority order to generate
// the reports in queuing priority order
for (i=0;i schedule(j,0);
}
s = new server(RUNNING);
sim -> hold(s);
// schedule a breakdown, it has the lowest scheduling priority so a
// customer first departs, if a breakdown occurs at the same time
b = new breakdown(BOTH_SERVERS_OK,-1);
sim -> schedule(b,0);
// run for RUNS lifetimes of the server
sim -> run();
// print results
for (i=0;i confidence(PERCENT95);
cout << (*alifetime);
cout << (*prob);
aprob = new analysis(prob);
aprob -> exponential();
cout << (*aprob);
delete lost;
delete lifetime;
delete prob;
delete alifetime;
delete aprob;
delete q;
delete sim;
}
fig D.3. The listing of the jobshop program
The following ASCII output was obtained :
Simulation started at 0.000000
Simulation stopped - quit called at 213640.080344
Created - 53385 events
Activated - 681816 events
Terminated - 53359 events
Actual time taken - 82 seconds
-------------------------------------------------------------------
waiting times for a customer with queuingpriority 0
mean = 17.511, variance = 246.715, std dev = 15.707
sum of frequencies = 6183
min val = 0.000, max val = 49.995
-------------------------------------------------------------------
waiting times for a customer with queuingpriority 1
mean = 15.372, variance = 204.220, std dev = 14.291
sum of frequencies = 14317
min val = 0.000, max val = 49.991
-------------------------------------------------------------------
waiting times for a customer with queuingpriority 2
mean = 8.782, variance = 82.108, std dev = 9.061
sum of frequencies = 21769
min val = 0.000, max val = 49.997
-------------------------------------------------------------------
waiting times for a customer with queuingpriority 3
mean = 0.928, variance = 9.208, std dev = 3.034
sum of frequencies = 7978
min val = 0.000, max val = 37.472
-------------------------------------------------------------------
total time spent for a customer with queuingpriority 0
mean = 22.350, variance = 270.269, std dev = 16.440
sum of frequencies = 5323
min val = 0.221, max val = 65.139
-------------------------------------------------------------------
total time spent for a customer with queuingpriority 1
mean = 20.383, variance = 234.780, std dev = 15.323
sum of frequencies = 12283
min val = 0.217, max val = 66.079
-------------------------------------------------------------------
total time spent for a customer with queuingpriority 2
mean = 13.929, variance = 129.825, std dev = 11.394
sum of frequencies = 18727
min val = 0.325, max val = 63.692
-------------------------------------------------------------------
total time spent for a customer with queuingpriority 3
mean = 5.183, variance = 33.611, std dev = 5.798
sum of frequencies = 7979
min val = 0.174, max val = 48.609
-------------------------------------------------------------------
number of interrupts for a customer with queuingpriority 0
mean = 0.147, variance = 0.170, std dev = 0.413
sum of frequencies = 14370
min val = 0.000, max val = 5.000
-------------------------------------------------------------------
number of interrupts for a customer with queuingpriority 1
mean = 0.101, variance = 0.114, std dev = 0.338
sum of frequencies = 12283
min val = 0.000, max val = 3.000
-------------------------------------------------------------------
number of interrupts for a customer with queuingpriority 2
mean = 0.138, variance = 0.155, std dev = 0.394
sum of frequencies = 18727
min val = 0.000, max val = 5.000
-------------------------------------------------------------------
number of interrupts for a customer with queuingpriority 3
mean = 0.000, variance = 0.000, std dev = 0.000
sum of frequencies = 7979
min val = 0.000, max val = 0.000
-------------------------------------------------------------------
lost jobs
0.00 5352.00#######################################################
1.00 3288.00###############################
2.00 407.00
3.00 0.00
fig D.4 The results(1)
As you can see, jobs having a higher priority have less waiting times.
The first three priorities have the same maximal waiting time, since
they are removed from the system when their waiting time is too long.
Furthermore, a job having the highest priority can't be interrupted and
it can't get lost.
-------------------------------------------------------------------
life time
mean = 21.254, variance = 451.600, std dev = 21.251
sum of frequencies = 10000
min val = 0.033, max val = 224.805
0.00 3777.00#######################################################
10.00 2353.00################################
20.00 1434.00#################
30.00 903.00########
40.00 588.00###
50.00 363.00
60.00 220.00
70.00 149.00##
80.00 81.00#
90.00 40.00
100.00 32.00
110.00 21.00
120.00 13.00
130.00 7.00
140.00 8.00
150.00 3.00
160.00 2.00
170.00 2.00
180.00 2.00
190.00 1.00
over 1.00
-------------------------------------------------------------------
CONFIDENCE : life time
level : 95
estimated mean : 21.25
interval : +/-0.42
-------------------------------------------------------------------
P(X > t) (%)
0.00 100.00#######################################################
5.00 79.64###########################################
10.00 62.23################################
15.00 49.34########################
20.00 38.70#################
25.00 30.44############
30.00 24.36#########
35.00 19.30#####
40.00 15.33###
45.00 12.04#
50.00 9.45
55.00 7.37
60.00 5.82
65.00 4.65##
70.00 3.62##
75.00 2.72#
80.00 2.13#
85.00 1.65#
90.00 1.32
95.00 1.15
over 4.96
-------------------------------------------------------------------
EXPONENTIAL FIT : P(X > t) (%)
a : 18.87
chi-square : 5.01
degree of freedom : 11
P(chi-square > 5.01) = 0.93
fig D.5 The results(2)
The statistics of the life time of the server and the chances
that this life time is greater then 0,5,10.. are given. The exponential
distribution has been fitted on the probability histogram of the
life times. A