#include #include #include #include using namespace std; enum DU_State { Up, Failed, Under_M }; enum Event_Type { DU_Failed, DU_Repaired, DU_Maint_Begin, DU_Maint_End, Simulation_Over }; class Dist_Unit { public: double lasteventtime; double uptime; double downtime; DU_State state; int id; }; class Event { public: Event_Type type; Dist_Unit *du; double time; }; typedef multimap EQ; class Simulation_System { public: Simulation_System(int argc, char **argv); void Run(); void Print_Event(Event *e); void Print_State(); void schedule_next_du_maintenance(Event *e); protected: int n; double duration; double beta_f; double eta_f; double beta_r; double eta_r; double gamma_r; double mi; double mt; vector dus; EQ eventq; double simtime; }; void Simulation_System::schedule_next_du_maintenance(Event *e) { e->type = DU_Maint_Begin; if (e->du->id == n-1) { e->du = dus[0]; e->time += mi; } else { e->du = dus[e->du->id+1]; } eventq.insert(make_pair(e->time, e)); } double gen_weibull(double beta, double eta, double gamma) { double tmp1, tmp2; tmp1 = -log(1.0 - drand48()); tmp2 = pow(tmp1, 1.0/beta); return eta * tmp2 + gamma; } void Simulation_System::Print_State() { int i; Event *e; EQ::iterator eqit; double uptime, downtime; cout << "--------------------------------\n"; cout << "Simulation Time: " << simtime << endl; for (i = 0; i < n; i++) { cout << "DU " << dus[i]->id << "'s state is " << dus[i]->state << endl; } for (eqit = eventq.begin(); eqit != eventq.end(); eqit++) { e = eqit->second; Print_Event(e); } uptime = 0; downtime = 0; for (i = 0; i < n; i++) { uptime += dus[i]->uptime; downtime += dus[i]->downtime; if (dus[i]->state == Up) { uptime += (simtime - dus[i]->lasteventtime); } else { downtime += (simtime - dus[i]->lasteventtime); } } cout << "Uptime: " << uptime << endl; cout << "Downtime: " << downtime << endl; cout << "--------------------------------\n"; } void Simulation_System::Print_Event(Event *e) { printf("%10.4lf ", e->time); switch(e->type) { case DU_Failed: printf("%-15s", "DU_Failed"); break; case DU_Repaired: printf("%-15s", "DU_Repaired"); break; case DU_Maint_Begin: printf("%-15s", "DU_Maint_Begin"); break; case DU_Maint_End: printf("%-15s", "DU_Maint_End"); break; case Simulation_Over: printf("%-15s", "Simulation_Over"); break; default: cerr << "This shouldn't happen\n"; exit(1); break; } if (e->type != Simulation_Over) { printf("%3d\n", e->du->id); } else { printf("\n"); } } Simulation_System::Simulation_System(int argc, char **argv) { int i; Dist_Unit *du; Event *e; if (argc != 10) { cerr << "usage: patron n duration(years) beta_f eta_f beta_r eta_r gamma_r maintenance_time maintenance_interval\n"; cerr << " all other units are days\n"; exit(1); } if (sscanf(argv[1], "%d", &n) != 1 || n <= 0) { cerr << "Bad n" << endl; exit(0); } if (sscanf(argv[2], "%lf", &duration) != 1 || duration <= 0) { cerr << "Bad duration" << endl; exit(0); } duration *= 365.0; if (sscanf(argv[3], "%lf", &beta_f) != 1 || beta_f <= 0) { cerr << "Bad beta_f" << endl; exit(0); } if (sscanf(argv[4], "%lf", &eta_f) != 1 || eta_f <= 0) { cerr << "Bad eta_f" << endl; exit(0); } if (sscanf(argv[5], "%lf", &beta_r) != 1 || beta_r <= 0) { cerr << "Bad beta_r" << endl; exit(0); } if (sscanf(argv[6], "%lf", &eta_r) != 1 || eta_r <= 0) { cerr << "Bad eta_r" << endl; exit(0); } if (sscanf(argv[7], "%lf", &gamma_r) != 1 || gamma_r < 0) { cerr << "Bad gamma_r" << endl; exit(0); } if (sscanf(argv[8], "%lf", &mt) != 1 || mt <= 0) { cerr << "Bad mt" << endl; exit(0); } if (sscanf(argv[9], "%lf", &mi) != 1 || mi <= 0) { cerr << "Bad mi" << endl; exit(0); } simtime = 0; for (i = 0; i < n; i++) { du = new Dist_Unit; du->id = i; du->lasteventtime = 0; du->uptime = 0; du->downtime = 0; du->state = Up; dus.push_back(du); } e = new Event; e->type = Simulation_Over; e->time = duration; e->du = NULL; eventq.insert(make_pair(e->time, e)); for (i = 0; i < n; i++) { e = new Event; e->type = DU_Failed; e->time = gen_weibull(beta_f, eta_f, 0.0); e->du = dus[i]; eventq.insert(make_pair(e->time, e)); } e = new Event; e->type = DU_Maint_Begin; e->time = mi; e->du = dus[0]; eventq.insert(make_pair(e->time, e)); } void Simulation_System::Run() { EQ::iterator eqit; Event *e; Dist_Unit *du; while(1) { eqit = eventq.begin(); if (eqit == eventq.end()) { cerr << "Event Queue is empty\n"; exit(1); } e = eqit->second; eventq.erase(eqit); simtime = e->time; Print_Event(e); switch(e->type) { case Simulation_Over: return; break; case DU_Maint_Begin: du = e->du; if (du->state == Failed) { schedule_next_du_maintenance(e); } else { cerr << "Maintenance not implemented yet\n"; exit(1); } break; case DU_Maint_End: schedule_next_du_maintenance(e); break; case DU_Failed: du = e->du; du->state = Failed; du->uptime += (simtime - du->lasteventtime); e->type = DU_Repaired; e->time = simtime + gen_weibull(beta_r, eta_r, gamma_r); du->lasteventtime = simtime; eventq.insert(make_pair(e->time, e)); break; case DU_Repaired: du = e->du; du->state = Up; du->downtime += (simtime - du->lasteventtime); e->type = DU_Failed; e->time = simtime + gen_weibull(beta_f, eta_f, 0.0); du->lasteventtime = simtime; eventq.insert(make_pair(e->time, e)); break; default: cerr << "Event not implemented " << e->type << endl; exit(1); } } } main(int argc, char **argv) { int ndu; int i; Simulation_System *ss; double simtime, mttf, mttr; srand48(0); ss = new Simulation_System(argc, argv); ss->Run(); ss->Print_State(); }