office ndoctors schedule-file seed trace |
Where:
patient-number appointment-time |
Patient numbers are integers and do not have to be unique. Appointment times are expressed as floating point numbers, whose units are hours. We assume that the doctor's office opens at 9:00 AM and closes at 5:00 PM. An appointment time of zero means 9:00 AM. An appointment time of 1.25 means 10:15 AM. Appointments are for 15 minutes. Any number of patients may be scheduled for any time, so you may specify a schedule where 100 patients are all scheduled to have appointments at 9:00 AM, if you want.
The following schedule files have been created for you. You will have to create some of your own though....
Office simulates one day in the doctor's office. To do this, it forks off one thread per doctor, and one thread per patient in the schedule file (i.e. one per line). The patients will arrive sometime near their appointment time -- sometimes early, and sometimes late (usually early). They enter the waiting room and wait in a FIFO fashion for a doctor. Any doctor will do. When a doctor is ready to see the patient, the appointment will take a random amount of time, from 3 minutes to a little over 38 minutes. The average time is 15 minutes (not exactly, but close enough). A patient may not arrive before 9:00 AM or after 5:00 PM; however he/she may be seen after 5:00 if the doctors are running late, or if he/she arrived late, and the appointment takes that long.
The doctors all arrive at 9:00, and wait, again in a FIFO fashion, for patients to arrive. When a patient arrives and a doctor is waiting, the doctor who has been waiting the longest sees the patient, and their appointment lasts the appropriate amount of time. When the appointment is over, the doctor either sees the next patient, or goes back to wait for more patients to arrive.
When all the patients are done with their appointments, the doctors all go home, and office prints out the following statistics:
So, let's look at some executions. First, let's run the simulation with one doctor on onepatient.txt, with tracing on and a seed of one:
UNIX> office 1 onepatient.txt 1 yes
0.000 Patient 1 will enter at 1.076
0.000 Doctor 0 is ready
1.076 Patient 1 enters waiting room
1.076 Patient 1 starting appointment (duration: 0.250) with doctor 0
1.076 Doctor 0 got patient 1. Appt time 0.250
1.326 Doctor 0 is ready
1.326 Patient 1 is done
1.326 Doctor 0 done for the day
SIMULATION STATISTICS
Number of patients: 1
Number of doctors: 1
Average appointment time (hours): 0.250
Avg Doctor idle time (hours/day): 7.750
Avg Patient wait time (hours/appt): 0.000
Latest a doctor goes home (hours after 5:00): 0.000
Average appointment time (hh:mm:ss): 00:14:59
Avg Doctor idle time (hh:mm:ss/day): 07:45:01
Avg Patient wait time (hh:mm:sss/appt): 00:00:00
Latest a doctor goes home (hh:mm:sss after 5:00): 00:00:00
Cash flow per doctor ($): 60.00
UNIX>
|
As you see, the patient was 0.076 hours late, and his appointment took 0.250 hours (15 minutes). The doctor was idle all day, except for those 15 minutes, so his idle time was 7.750 hours. He went home at 5:00. The patient didn't have to wait, so the average patient wait time was 0.000 hours.
Note, the hh:mm:ss time shows that the appointment time was not exacly 15 minutes. That's ok -- these are doubles, and office only prints out three decimal places.
If you give the program a different seed, you'll get different results:
UNIX> office 1 onepatient.txt 2 yes
0.000 Patient 1 will enter at 0.976
0.000 Doctor 0 is ready
0.976 Patient 1 enters waiting room
0.976 Patient 1 starting appointment (duration: 0.161) with doctor 0
0.976 Doctor 0 got patient 1. Appt time 0.161
1.137 Doctor 0 is ready
1.137 Patient 1 is done
1.137 Doctor 0 done for the day
SIMULATION STATISTICS
Number of patients: 1
Number of doctors: 1
Average appointment time (hours): 0.161
Avg Doctor idle time (hours/day): 7.839
Avg Patient wait time (hours/appt): 0.000
Latest a doctor goes home (hours after 5:00): 0.000
Average appointment time (hh:mm:ss): 00:09:40
Avg Doctor idle time (hh:mm:ss/day): 07:50:20
Avg Patient wait time (hh:mm:sss/appt): 00:00:00
Latest a doctor goes home (hh:mm:sss after 5:00): 00:00:00
Cash flow per doctor ($): 60.00
UNIX>
|
As you can see, this time, the patient arrived early (0.024 hours), and the appointment was quick -- only 9 minutes and 40 seconds.
Take a look at running office on twopatients.txt, with tracing on and a seed of two:
UNIX> office 1 twopatients.txt 2 yes
0.000 Patient 1 will enter at 0.976
0.000 Patient 2 will enter at 0.898
0.000 Doctor 0 is ready
0.898 Patient 2 enters waiting room
0.898 Patient 2 starting appointment (duration: 0.126) with doctor 0
0.898 Doctor 0 got patient 2. Appt time 0.126
0.976 Patient 1 enters waiting room
1.024 Doctor 0 is ready
1.024 Doctor 0 got patient 1. Appt time 0.161
1.024 Patient 1 starting appointment (duration: 0.161) with doctor 0
1.024 Patient 2 is done
1.185 Patient 1 is done
1.185 Doctor 0 is ready
1.185 Doctor 0 done for the day
SIMULATION STATISTICS
Number of patients: 2
Number of doctors: 1
Average appointment time (hours): 0.144
Avg Doctor idle time (hours/day): 7.713
Avg Patient wait time (hours/appt): 0.024
Latest a doctor goes home (hours after 5:00): 0.000
Average appointment time (hh:mm:ss): 00:08:37
Avg Doctor idle time (hh:mm:ss/day): 07:42:45
Avg Patient wait time (hh:mm:sss/appt): 00:01:26
Latest a doctor goes home (hh:mm:sss after 5:00): 00:00:00
Cash flow per doctor ($): 120.00
|
Now, patient 1 entered 0.024 hours early, and patient 2 entered earlier (0.102 hours early). Thus, the doctor saw patient 2 first. The appointment lasted 0.126 hours, meaning that it completed 1.024 hours after 9:00 AM. At that point, the doctor saw patient #1, who had been waiting 0.048 hours.
The statistics reflect this. The doctor was idle for 8 hours with the exception of the 0.126+0.161=0.287 hours when he saw the two patients. The average patient wait time is 0.24 hours (patient 1 waited 0.048 hours, and patient 2 didn't wait at all).
If we add a second doctor, we get more doctor idle time, and no patient wait time:
0.000 Patient 1 will enter at 0.976
0.000 Patient 2 will enter at 0.898
0.000 Doctor 0 is ready
0.000 Doctor 1 is ready
0.898 Patient 2 enters waiting room
0.898 Patient 2 starting appointment (duration: 0.126) with doctor 0
0.898 Doctor 0 got patient 2. Appt time 0.126
0.976 Patient 1 enters waiting room
0.976 Patient 1 starting appointment (duration: 0.161) with doctor 1
0.976 Doctor 1 got patient 1. Appt time 0.161
1.024 Doctor 0 is ready
1.024 Patient 2 is done
1.137 Doctor 1 is ready
1.137 Patient 1 is done
1.137 Doctor 0 done for the day
1.137 Doctor 1 done for the day
SIMULATION STATISTICS
Number of patients: 2
Number of doctors: 2
Average appointment time (hours): 0.144
Avg Doctor idle time (hours/day): 7.856
Avg Patient wait time (hours/appt): 0.000
Latest a doctor goes home (hours after 5:00): 0.000
Average appointment time (hh:mm:ss): 00:08:37
Avg Doctor idle time (hh:mm:ss/day): 07:51:23
Avg Patient wait time (hh:mm:sss/appt): 00:00:00
Latest a doctor goes home (hh:mm:sss after 5:00): 00:00:00
Cash flow per doctor ($): 60.00
|
UNIX> office 3 onelate.txt 1 yes
0.000 Patient 1 will enter at 7.826
0.000 Doctor 0 is ready
0.000 Doctor 1 is ready
0.000 Doctor 2 is ready
7.826 Patient 1 enters waiting room
7.826 Patient 1 starting appointment (duration: 0.250) with doctor 0
7.826 Doctor 0 got patient 1. Appt time 0.250
8.076 Doctor 0 is ready
8.076 Patient 1 is done
8.076 Doctor 1 done for the day
8.076 Doctor 2 done for the day
8.076 Doctor 0 done for the day
SIMULATION STATISTICS
Number of patients: 1
Number of doctors: 3
Average appointment time (hours): 0.250
Avg Doctor idle time (hours/day): 7.942
Avg Patient wait time (hours/appt): 0.000
Latest a doctor goes home (hours after 5:00): 0.076
Average appointment time (hh:mm:ss): 00:14:59
Avg Doctor idle time (hh:mm:ss/day): 07:56:31
Avg Patient wait time (hh:mm:sss/appt): 00:00:00
Latest a doctor goes home (hh:mm:sss after 5:00): 00:04:32
Cash flow per doctor ($): 20.00
|
You see that the patient's appointment goes past 5:00, and doctor zero has to stay past 5:00. This is reflected in the statistics. We assume that the other doctors go home at 5:00 though, so the idle time is 8 hours each for doctors 1 & 2, and 7.826 hours for doctor zero. That averages to 7.942 hours.
Finally, we can run office on the very doctor-friendly schedule allnine.txt:
UNIX> office 1 allnine.txt 1 no SIMULATION STATISTICS Number of patients: 32 Number of doctors: 1 Average appointment time (hours): 0.253 Avg Doctor idle time (hours/day): 0.000 Avg Patient wait time (hours/appt): 3.845 Latest a doctor goes home (hours after 5:00): 0.081 Average appointment time (hh:mm:ss): 00:15:09 Avg Doctor idle time (hh:mm:ss/day): 00:00:00 Avg Patient wait time (hh:mm:sss/appt): 03:50:42 Latest a doctor goes home (hh:mm:sss after 5:00): 00:04:51 Cash flow per doctor ($): 1920.00 |
As you see, the doctor is never idle, and this schedule obviously achieves the maximum patient throughput. However, the average patient wait time is nearly four hours. It seems to me that I've been to this doctor before......
Additionally, you are to email me (not the TA's, but me), your best schedule. This schedule must:
You have to email me your schedule (it will be a certain number of points) -- that's all you'll be graded on -- how it performs is only for pride -- I'll show the best ones in class.
For example, if you have an office with one doctor and use uniform.txt, then in 100 runs (seeds 0 through 99), you get:
Office.h contains definitions for structs and for the routines that you need to write in office.c. First, there is the main struct for the simulation:
typedef struct {
int ndoctors;
int npatients;
int trace;
double now;
void *v;
} Simulation_info;
|
There is one of these, which will be passed to every doctor and patient. The first three fields are from the command line arguments. Your simulator will keep track of simulated time with the variable now, which is the number of hours since 9:00 AM. V is a (void *) that you will define and use to help manage the simulation and keep track of the statistics.
Next, there are structs for doctors and patients:
typedef struct {
int id;
kt_sem sem;
Simulation_info *s;
void *v;
} Doctor;
typedef struct {
int id;
double arrival;
double duration;
kt_sem sem;
Simulation_info *s;
void *v;
} Patient;
|
Each has an id number, a pointer to the main simulation struct, and a semaphore that you can use to make the doctor/patient wait. Each also has a (void *) called v that you can define and use. Additionally, patients have an arrival time (hours after 9:00 AM) and an appointment duration.
There are nine procedures that you have to write:
This is the driver program, that consists of the main() program, which reads the schedule and creates patient/doctor threads. This is where the patient arrival times and appointment durations are generated. It waits for all the threads to exit and then calls finalize_simulation. The patient and doctor threads are straightforward. Also, all tracing calls are here.
The doctor and patient threads are rather simple: (trace calls removed):
void *patient(void *arg)
{
Patient *p;
Doctor *d;
p = (Patient *) arg;
initialize_patient(p);
wait_until(p->s, p->arrival, p->sem);
d = wait_for_doctor(p);
wait_until(p->s, p->s->now + p->duration, p->sem); /* Do the appointment */
finalize_patient(p);
return NULL;
}
|
void *doctor(void *arg)
{
Doctor *d;
Patient *p;
d = (Doctor *) arg;
initialize_doctor(d);
while (1) {
p = get_patient(d);
if (p == NULL) { finalize_doctor(d); return NULL; }
wait_until(d->s, d->s->now + p->duration, d->sem); /* Do the appointment */
}
}
|
Note, you cannot assume that semaphore block and unblock as FIFO's -- you have to enforce FIFO order yourself.
Have fun, and remember all parts of the assignment.