以下,複数のファイル構成になっていますので,ファイル間の 区切りを「---・・・」で示します. ------------------------makefile------------------ # # リンク # CFLAGS = -c -Wall -O2 OBJECT = machi.o Q_base.o Customer.o pgm: $(OBJECT) g++ $(OBJECT) -o machi -lm # # コンパイル # machi.o: machi.h machi.cpp g++ $(CFLAGS) machi.cpp Q_base.o: machi.h Q_base.cpp g++ $(CFLAGS) Q_base.cpp Customer.o: machi.h Customer.cpp g++ $(CFLAGS) Customer.cpp ------------------------machi.h------------------- /****************************/ /* クラスCustomerの定義 */ /****************************/ class Customer { double time; // 到着時刻 int num; // 客番号 int state; // 客の状態 // =-1 : 待ち行列に入っている // >=0 : サービスを受けている窓口番号 double time; // 到着時刻 Customer *next; public : Customer (int, int, double); // コンストラクタ Customer (); void Add(Customer *); // 客の追加 void Change(int, int); // 状態の変更 void Del(int); // 客の削除 int Search(); // 待ち行列の先頭にいる客を捜す double Search(int); // 指定した客の到着時間 }; /***************************/ /* クラスQ_baseの定義 */ /***************************/ class Q_base { int s; // 窓口の数 int asb; // 全窓口の空き状況 // =0 : すべての窓口がふさがっている // =n : n個の窓口が空いている int *sb; // 各窓口の空き状況 // =0 : 窓口は空いている // >0 : サービスを受けている客番号 double asb_t; // すべての窓口がふさがった時間 double c_asb; // すべての窓口がふさがっている時間の累計 double *c_sb; // 各窓口がふさがっている時間の累計 double *st_e; // 各窓口のサービス終了時間 double *st_s; // 各窓口がふさがった時間 int lq; // 現在の待ち行列の長さ int m_lq; // 最大待ち行列長 int tq; // 待ち行列の先頭にいる客番号 double c_lq_t; // 待ち行列長にその長さが継続した時間を乗じた値の累計 double c_wt; // 待ち時間の累計 double lq_t; // 現在の待ち行列長になった時間 double m_wt; // 最大待ち時間 int sc; // 現在の系内客数 double c_sc_t; // 系内客数にその数が継続した時間を乗じた値の累計 double c_sys; // 滞在時間の累計 double m_sys; // 最大滞在時間 double sc_t; // 現在の系内客数になった時間 int m_sc; // 最大系内客数 double m_a; // 到着時間間隔の平均値 double m_s; // サービス時間の平均値 double at; // 次の客の到着時間(負の時は,終了) double p_time; // 現在時間 double end; // シミュレーション終了時間 int nc; // 到着客数カウンタ public: Q_base(int, double, double, double); // コンストラクタ ~Q_base(); // デストラクタ double Next_at(); // 次の到着時刻 double Next_sv(); // サービス終了時刻 void Control(); // 全体の制御 int Next(); // 次の処理の決定 int End_o_s(); // 終了処理 void Arrive(Customer &); // 客の到着処理 void Service(int, Customer &); // サービス終了 void Output(); // 出力 }; ------------------------Customer.cpp-------------- /************************************/ /* クラスCustomerのメンバー関数 */ /************************************/ #include #include #include "machi.h" /***********************/ /* コンストラクタ */ /* n : 客番号 */ /* s : 状態 */ /***********************/ Customer::Customer (int n, int s, double t) { time = t; num = n; state = s; next = NULL; } /********************************/ /* 引数無しのコンストラクタ */ /********************************/ Customer::Customer () { next = NULL; } /**********************************************/ /* 客をリストの最後に追加 */ /* dt : Customerクラスのオブジェクト */ /**********************************************/ void Customer::Add(Customer *dt) { Customer *lt = this; while (lt->next != NULL) lt = lt->next; lt->next = dt; } /***********************/ /* 状態の変更 */ /* n : 客番号 */ /* s : 状態 */ /***********************/ void Customer::Change(int n, int s) { Customer *lt = this; int sw = 1; while (sw > 0) { // データが存在しない場合 if (lt->next == NULL) { printf(" 指定されたデータがありません(Change)!\n"); exit(1); } // 比較し,変更 else { lt = lt->next; if (n == lt->num) { lt->state = s; sw = 0; } } } } /***********************/ /* 客の削除 */ /* n : 客番号 */ /***********************/ void Customer::Del(int n) { Customer *lt1, *lt2 = this; int sw = 1; while (sw > 0) { // データが存在しない場合 if (lt2->next == NULL) { printf(" 指定されたデータがありません(Del)!\n"); exit(1); } // 比較し,削除 else { lt1 = lt2; lt2 = lt2 -> next; if (n == lt2->num) { lt1->next = lt2->next; sw = 0; } } } } /**************************************/ /* 待ち行列の先頭の客を捜す */ /* return : 先頭の客番号 */ /* (負の時は無し) */ /**************************************/ int Customer::Search() { Customer *lt = this; int n = -1; while (n < 0) { // データが存在しない場合 if (lt->next == NULL) { printf(" 指定されたデータがありません(Search_q)!\n"); exit(1); } // 探索 else { lt = lt->next; if (lt->state < 0) n = lt->num; } } return n; } /******************************/ /* 指定した客の到着時間 */ /* nm : 客番号 */ /* return : 到着時間 */ /******************************/ double Customer::Search(int nm) { Customer *lt = this; double t = 0.0; int sw = -1; while (sw < 0) { // データが存在しない場合 if (lt->next == NULL) { printf(" 指定されたデータがありません(Search)!\n"); exit(1); } // 探索 else { lt = lt->next; if (lt->num == nm) { sw = 0; t = lt->time; } } } return t; } ------------------------Q_base.cpp---------------- /**********************************/ /* クラスQ_baseのメンバー関数 */ /**********************************/ #include #include #include #include "machi.h" double drand48(); /*********************************************/ /* コンストラクタ */ /* s_i : 窓口の数 */ /* m_a_i : 到着時間間隔の平均値 */ /* m_s_i : サービス時間の平均値 */ /* end_i : シミュレーション終了時間 */ /*********************************************/ Q_base::Q_base (int s_i, double m_a_i, double m_s_i, double end_i) { int i1; /* 設定 */ s = s_i; m_a = m_a_i; m_s = m_s_i; end = end_i; /* 領域の確保 */ sb = new int [s]; c_sb = new double [s]; st_e = new double [s]; st_s = new double [s]; for (i1 = 0; i1 < s; i1++) { sb[i1] = 0; c_sb[i1] = 0.0; } /* 初期設定 */ p_time = 0.0; nc = 0; asb = s; lq = 0; sc = 0; m_lq = 0; m_sc = 0; c_asb = 0.0; c_wt = 0.0; m_wt = 0.0; c_lq_t = 0.0; lq_t = 0.0; m_sys = 0.0; c_sys = 0.0; c_sc_t = 0.0; sc_t = 0.0; /* 乱数の初期設定 */ srand(12345); /* 最初の客の到着時間の設定 */ at = p_time + Next_at(); } /********************/ /* デストラクタ */ /********************/ Q_base::~Q_base() { delete [] sb; delete [] c_sb; delete [] st_e; delete [] st_s; } /**************************************/ /* 次の客の到着までの時間の発生 */ /**************************************/ double Q_base::Next_at() { return -m_a * log(drand48()); } /****************************/ /* サービス時間の発生 */ /****************************/ double Q_base::Next_sv() { return -m_s * log(drand48()); } /******************/ /* 全体の制御 */ /******************/ void Q_base::Control() { int sw = 0; Customer ct; while (sw > -2) { // 次の処理の選択 sw = Next(); if (sw == -1) // シミュレーションの終了 sw = End_o_s(); // シミュレーション else { if (sw == 0) // 客の到着処理 Arrive(ct); else // サービスの終了 Service(sw, ct); } } } /********************************************************/ /* 次の処理の決定 */ /* return : =-1 : シミュレーションの終了 */ /* =0 : 客の到着処理 */ /* =i : i番目の窓口のサービス終了 */ /********************************************************/ int Q_base::Next() { int i1, sw; double t; sw = -1; t = end; if (at >= 0.0 && at < t) { sw = 0; t = at; } for (i1 = 0; i1 < s; i1++) { if (sb[i1] > 0 && st_e[i1] <= t) { sw = i1+1; t = st_e[i1]; } } return sw; } /**************************************/ /* 終了処理 */ /* return : =-1 : 終了前処理 */ /* =-2 : 実際の終了 */ /**************************************/ int Q_base::End_o_s() { int i1, sw; sw = -2; p_time = end; at = -1.0; for (i1 = 0; i1 < s; i1++) { if (sb[i1] > 0) { if (sw == -2) { sw = -1; end = st_e[i1]; } else { if (st_e[i1] > end) end = st_e[i1]; } } } return sw; } /********************************/ /* 客の到着処理 */ /* ct : 客リストの先頭 */ /********************************/ void Q_base::Arrive(Customer &ct) { int i1, k; Customer *ct_p; /* 客数の増加と次の客の到着時刻の設定 */ nc += 1; p_time = at; at = p_time + Next_at(); // 次の客 /* 系内客数の処理 */ sc += 1; c_sc_t += (double)(sc - 1) * (p_time - sc_t); sc_t = p_time; if (sc > m_sc) m_sc = sc; /* 待ち行列があるか、または、窓口に空きがない場合 */ if (lq > 0 || asb == 0) { ct_p = new Customer (nc, -1, p_time); ct.Add(ct_p); // 客の登録 lq += 1; if (lq == 1) tq = nc; c_lq_t += (double)(lq - 1) * (p_time - lq_t); lq_t = p_time; if (lq > m_lq) m_lq = lq; } /* すぐサービスをうけれる場合 */ else { k = -1; for (i1 = 0; i1 < s && k < 0; i1++) { if (sb[i1] == 0) { ct_p = new Customer (nc, i1, p_time); ct.Add(ct_p); // 客の登録 k = i1; sb[k] = nc; st_e[k] = p_time + Next_sv(); asb -= 1; } } st_s[k] = p_time; if (asb == 0) asb_t = p_time; } } /*************************************/ /* サービス終了時の処理 */ /* k : サービス終了窓口番号 */ /* ct : 客リストの先頭 */ /*************************************/ void Q_base::Service(int k, Customer &ct) { int i1; double x1; /* 時間の設定 */ k -= 1; p_time = st_e[k]; /* 系内客数の処理 */ sc -= 1; c_sc_t += (double)(sc + 1) * (p_time - sc_t); sc_t = p_time; /* 滞在時間の処理 */ x1 = p_time - ct.Search(sb[k]); c_sys += x1; if (x1 > m_sys) m_sys = x1; ct.Del(sb[k]); // 客の削除 /* 窓口使用時間の処理 */ asb += 1; sb[k] = 0; c_sb[k] += (p_time - st_s[k]); /* 待ち行列がある場合 */ if (lq > 0) { asb -= 1; lq -= 1; c_lq_t += (double)(lq + 1) * (p_time - lq_t); lq_t = p_time; x1 = p_time - ct.Search(tq); c_wt += x1; if (x1 > m_wt) m_wt = x1; k = -1; for (i1 = 0; i1 < s && k < 0; i1++) { if (sb[i1] == 0) { k = i1; sb[k] = tq; st_e[k] = p_time + Next_sv(); st_s[k] = p_time; ct.Change(tq, k); } } if (lq > 0) tq = ct.Search(); } /* 待ち行列がない場合 */ else { if (asb == 1) c_asb += (p_time - asb_t); } } /****************************/ /* 結果の出力 */ /* (カッコ内は理論値) */ /****************************/ void Q_base::Output() { int i1; double L, Lq, myu, p0, pi, ram, rn, rou, rs, W, Wq; rn = (double)nc; rs = (double)s; ram = 1.0 / m_a; myu = 1.0 / m_s; rou = ram / (rs * myu); if (s == 1) { p0 = 1.0 - rou; pi = rou; } else { p0 = 1.0 / (1.0 + 2.0 * rou + 4.0 * rou * rou / (2.0 * (1.0 - rou))); pi = 4.0 * rou * rou * p0 / (2.0 * (1.0 - rou)); } Lq = pi * rou / (1.0 - rou); L = Lq + rs * rou; Wq = Lq / ram; W = Wq + 1.0 / myu; printf("シミュレーション終了時間=%10.5f 客数=%d ρ=%10.5f p0=%10.5f\n", p_time, nc, rou, p0); printf(" すべての窓口が塞がっている割合=%5.3f (%10.5f)\n", c_asb/p_time, pi); printf(" 各窓口が塞がっている割合\n"); for (i1 = 0; i1 < s; i1++) printf(" %3d %5.3f\n", i1+1, c_sb[i1]/p_time); printf(" 平均待ち行列長=%7.3f (%10.5f) 最大待ち行列長=%3d\n", c_lq_t/p_time, Lq, m_lq); printf(" 平均系内客数 =%7.3f (%10.5f) 最大系内客数 =%3d\n", c_sc_t/p_time, L, m_sc); printf(" 平均待ち時間 =%7.2f (%10.5f) 最大待ち時間 =%7.2f\n", c_wt/rn, Wq, m_wt); printf(" 平均滞在時間 =%7.2f (%10.5f) 最大滞在時間 =%7.2f\n", c_sys/rn, W, m_sys); } ------------------------main---------------------- /**********************************/ /* 簡単な待ち行列問題(M/M/s)*/ /* coded by Y.Suganuma */ /**********************************/ #include #include #include "machi.h" /**********************************/ /* [0, 1]区間の一様乱数の発生 */ /* rerutn : 乱数 */ /**********************************/ double drand48(void) { double x; while ((x = (double)rand() / RAND_MAX) == 0.0) ; return x; } /********************/ /* main program */ /********************/ int main() { int s; double end, m_a, m_s; /* 入力データ */ printf("窓口の数は? "); scanf("%d", &s); printf("シミュレーション終了時間? "); scanf("%lf", &end); printf(" 到着時間間隔の平均値は? "); scanf("%lf", &m_a); printf(" サービス時間の平均値は? "); scanf("%lf", &m_s); /* システムの定義 */ Q_base base(s, m_a, m_s, end); /* シミュレーションの実行 */ base.Control(); /* 出力 */ base.Output(); return 0; }