• ベストアンサー

難プログラミングです。

待ち行列のシミュレーション問題です。 頭を抱えているので、良かったらプログラミングがお分かりになる方、 レスポンスいただけますでしょうか。ちなみにVBAでやっています。 ある店の5分あたりの来客数は、お昼時に平均4人、夕食時は平均3人、その他の時間帯は平均2人のポアソン分布にそれぞれ近似的に従っている。(各時間帯は3時間ずつ)カウンターでお客を一人処理するのに必要な時間は一律5分である。ただし、待ち行列は1つだけとする。(カウンタごとに待ち行列をつくるのではない)以下のシュミレーションを行った上で検討せよ。 1.店舗の収益をできるだけ多くする観点からは、各時間帯においてカ ウンターを幾つ稼動させるのが望ましいか。(カウンター店員の自給 や客1人あたりの利益等各自で適当に与えて検討) 2.客があまり長時間待つことがないようにする。例えば行列で5人以 上が待つようなことが10日に1回以下しか起こらないようにする。そ のためには、各時間帯においてカウンターをいくつ稼動するのが望ま しいか。

質問者が選んだベストアンサー

  • ベストアンサー
  • stomachman
  • ベストアンサー率57% (1014/1775)
回答No.3

 5分刻みでカウンターと待ち行列の状態を見ているのでは、その5分の間に「(a)ひとりの客が来て待ち行列に加わり、(b)カウンターでひとりの客の応対が終わった」というのが正しく処理できるでしょうか。(a)と(b)のどちらが先に生じたかで、その5分の間に待ち行列の長さの最大値が違ってきますぜ。 ●イベント・ドリブン(event driven)で考えた方が良いんじゃないかなー。ここでイベントというのは、 「j番目の客が来る」という出来事と、 「(どれかのカウンターで)j番目の客の応対が終わる」という出来事 です。時間を等間隔に区切るのではなくて、そういう出来事が生じた時点だけに注目して処理を行うんです。 ●カウンターがn個あるとしましょう。 j番目の客が来た時刻t[j]において、カウンターが応対しているうちで一番早く来た客はk番目の客だとします。  もし、j-k<nなら、待ち行列はありません。カウンターは(j-k)+1人(j番目の客を含めて)に応対中で、空いているカウンターはn-((j-k)+1)個です。  もし、j-k≧nなら、待ち行列に((j-k)+1)-n人(j番目の客を含めて)並んでいて、空いているカウンターは0個です。 ●さて、「j番目の客が来た時刻t[j]から j+1番目の客が来た時刻t[j+1]の直前までの時間に何が起こったか」を考えますと、 1. t[j]から t[j+1]の直前まで客は一人も来ていない。 2. k番目の客の応対が終わる時刻はt[k]+5(分)、k+1番目の客の応対が終わる時刻はt[k+1]+5(分)、…と分かっています。そして、「応対が終わる」というイベントが生じる度に   もし待ち行列があれば、長さがひとつ減る。   もし待ち行列がなければ、空いているカウンターが一つ増える。 ということが起こります。  だから、例えば、 もし t[k]+5(分)< t[j+1] であって、しかも待ち行列があれば、   時刻t[j]に長さ((j-k)+1)-nだった待ち行列が、時刻t[k]+5(分)に長さ((j-k)+1)-n-1になる。つまり、t[j]から t[j+1]の直前までの時間の中で、待ち行列が長さ((j-k)+1)-nだった時間はt[k]+5(分)-t[j]である。  さらに もし t[k+1]+5(分)< t[j+1] であって、しかも待ち行列があれば、  (t[k]+5(分)< t[k+1]+5(分)であるから)   時刻t[k]+5(分)に長さ((j-k)+1)-n-1だった待ち行列が、時刻t[k+1]+5(分)に長さ((j-k)+1)-n-2になる。つまり、t[j]から t[j+1]の直前までの時間の中で、待ち行列が長さ((j-k)+1)-n-1だった時間はt[k+1]-t[k]である。 という具合です。  以下、t[k+m]+5(分)<t[j+1]である最大のmまで同様です。(もちろん、待ち行列が0になった場合には、以後の処理の中身が違います。)  従って、時刻t[j+1]の直前の時点で、カウンターが応対しているうちで一番早く来た客はk+m+1番目の客です。  で、時刻t[j+1]の直前の時点でカウンターが全て稼働中で長さL(L≧0)の待ち行列があったとします。そこに時刻t[j+1]に新しい客が来ると、待ち行列がひとつ伸びる。ですから、「t[j]から t[j+1]の直前までの時間の中で、待ち行列が長さLだった時間」はt[j+1]-(t[k+m]+5(分))です。  一方、時刻t[j+1]の直前の時点でカウンターがひとつでも空いていたとしますと、時刻t[j+1]に新しい客が来ると、空いているカウンターが一つ減ります。 ●従って、「営業開始からt[j+1] の直前までの間に、待ち行列の長さがLだった時間」を表す配列S[L]を用意して、待ち行列の長さが変化する度に累計して行けば良いですね。 ●ところで、客が来るというイベントをどうやって発生させれば良いか。ポアソン分布に従って客が来るということは、j番目の客が来た時刻t[j]とj+1番目の客が来た時刻t[j+1]との間隔( t[j+1]-t[j] )が指数分布に従うということです。その間隔がTよりも大きい確率Pは P=1-exp(-λT) ということになりますから、0から1までの一様乱数に従う値rを一つ発生して r=1-exp(-λT) となるTを計算すれば、t[j+1] = t[j]+Tが計算できます。 ★「行列が出来る店」は開店前に既に列が出来てますねー。あと、閉店時刻にまだ行列が残っていたときにどうするんだろ?(お構いなしに「はい、本日終わりです」と店を閉めてしまうかどうか。)これらをどう扱うかは問題には指定されていないようで、自分で設定しなくちゃいけませんね。  ところで、もっとリアルにするには、列が長くなるにつれて並ぶのを諦める客が増える(λが小さくなる)ようにするとか、カウンターでの応対時間にばらつきを持たせる(到着順に応対が終わるとは限らなくなるので、どのカウンターがどの客を応対中かを示すデータを保持する必要があります)などが考えられます。いろいろ遊べます。  なお、「はい、本日終わりです」方式において人件費の低減だけを考えれば、どんなに列が長くなろうがカウンターは1個が最適であるのは自明です(どこかのブランド店とか、ソ連時代のモスクワの売店みたいです)。が、それだと機会損失(客が来ているのに販売を断ることで、得られた筈の利益をのがすこと)が生じます。この問題には(捌けた客の人数×客単価×利益率-店員の人件費)を最大にしたいという動機がある訳ですね。

その他の回答 (2)

回答No.2

以下の2点を直せば、コンパイルは通るようです。  If t / 5 = Int(t / 5) Then に対応する End If がない  If mean = 1 Then に対応する End If がない OKWave上ではどうしてもレイアウトが崩れてしまうのですが、 インデント(字下がり)はつけていますか? インデントをつけておけば、 どの If と End If が対応しているか、すぐにわかります。

micoo38
質問者

お礼

インデントは付けていたのですが、何か手違いがありました。 おかげさまで、コンパイルは直りました。 本当にありがとうございます。 しかしながら、このソースが合っていると思えないのです。 「お昼時に平均4人、夕食時は平均3人」というプログラミングを 入力しなければならないと思うのですが・・・ 頭がこんがらがります。。 お時間あるときでかまいませんので、また返信していただけると 幸いです。

回答No.1

5分あたりの来客数が平均4人の平均ポアソン分布に従うということは、例えば、 最初の5分の来客数は2人 次の5分の来客数は7人 次の5分の来客数は3人 次の5分の来客数は5人 次の5分の来客数は2人 次の5分の来客数は3人 次の5分の来客数は4人 次の5分の来客数は4人 次の5分の来客数は5人 次の5分の来客数は5人 (上記の平均は4.2人) ということになります。(VBAで実験しました。) 問題は、上記の来客数をどうやって発生させるかになります。 0~1の乱数を発生させる Rnd 関数はありますので、 その乱数をポアソン分布を使って来客数に変換すればいいことになります。 とりあえずここまでにします。 考えてみてわからなければご質問下さい。

micoo38
質問者

お礼

わざわざ、実験までしていただき、ありがとうございます。 以下に現在奮闘中のソースを貼ります。 コンパイルエラーが出るので、間違っていることは確かなのですが もしよろしければ、何が足らないのか教えてくださりませんでしょうか。

micoo38
質問者

補足

Sub shop() '変数の宣言 Dim period, mean, counter, speed, arrival, queue, process, total, t As Integer Dim r As Double 'シミュレーション条件の入力 period = InputBox("シミュレーション時間(分)を入力してください(5以上の整数)") mean = InputBox("5分あたり平均来客数を入力してください(1~3の整数)") counter = InputBox("カウンタ数を入力してください(1以上の整数)") speed = InputBox("5分あたりカウンタ処理数を入力してください(1以上の整数)") '初期化 Randomize arrival = 0: queue = 0 Cells(1, 1).Value = "経過時間(分)": Cells(2, 1).Value = 0 Cells(1, 2).Value = "待ち行列人数(人)" Cells(1, 3).Value = "新規来客数(人)" Cells(1, 4).Value = "カウンタ処理数(人)" '時間進行 For t = 0 To period '単位時間5分 If t / 5 = Int(t / 5) Then '乱数の発生 r = Rnd() '5分当たりの来客数 '   平均1の場合 If mean = 1 Then If r < 0.368 Then arrival = 0 ElseIf r < 0.736 Then arrival = 1 ElseIf r < 0.92 Then arrival = 2 ElseIf r < 0.981 Then arrival = 3 ElseIf r < 0.996 Then arrival = 4 Else arrival = 5 End If '   平均2~4の場合も同様 '来客総数 total = total + arrival '待ち行列人数の増加 process = counter * speed queue = queue + arrival - process If queue < 0 Then process = process + queue: queue = 0 End If '5分毎の結果の表示 Cells(Int(t / 5) + 2, 3).Value = arrival Cells(Int(t / 5) + 2, 4).Value = process Cells(Int(t / 5) + 3, 1).Value = t + 5 Cells(Int(t / 5) + 3, 2).Value = queue Next '来客総数の表示 msg = MsgBox(total & "人", vbInformation + vbOKOnly, "来客総数") End Sub

関連するQ&A

  • ポアソンの待ち行列、M/M/1について教えて下さい。

    ポアソンの待ち行列、M/M/1について教えて下さい。 レジがひとつあります。 1時間に12人の客がポアソン到着します。 1人あたりの平均サービス時間は4分で、指数分布に従っています。 この時、レジを待つ人の平均人数を1人以下にするには、レジのサービス能力をいくら以上にすれば良いでしょうか? 大学で学んだのですが、この部分がよく解りませんでした。

  • 学校課題のプログラミングにとても悩まされています…。

    学校課題のプログラミングにとても悩まされています…。 学校でC言語でプログラミングせよ。 との課題が出たのですが、プログラミングが全くわからなくて困っています!! お願いします!!誰か助けて下さい!! 待ち行列 ・レジ到着は一時間あたり平均20人。 ・客は一番待ち人数の少ないレジに並ぶ。 ・待ち人数の同じレジが二つ以上ある場合は等確率でその内の一つをランダムに選択。 ・客一人あたりの勘定時間は平均値10分の指数分布 ・一つの勘定台には最長平均5分までしか客を待たせられない レジの必要数の推定と客の平均待ち時間およびレジの平均空き時間を推定せよ。 ともありますが、さっぱりです…。

  • 学校で、C言語でのプログラミングをせよ。

    学校で、C言語でのプログラミングをせよ。 との課題が出たのですが、プログラミングが全くわからなくて困っています!! 誰か助けて下さい!! 待ち行列 ・レジ到着は一時間あたり平均20人。 ・客は一番待ち人数の少ないレジに並ぶ。 ・待ち人数の同じレジが二つ以上ある場合は等確率でその内の一つをランダムに選択。 ・客一人あたりの勘定時間は平均値10分の指数分布 ・一つの勘定台には最長平均5分までしか客を待たせられない レジの必要数の推定と客の平均待ち時間およびレジの平均空き時間を推定せよ。 ともありますが、さっぱりです…。

    • ベストアンサー
    • Java
  • MTBFについて

    ----||--|----||--|----||-- 上の初めから最後までが全運転時間(60分)で、 ----(15分)が稼動時間 ||が故障発生 --(5分)が修復時間 です。 MTBFは 稼働時間の合計÷故障回数 //★1 となっているので、 (15+15+15)÷3=15分で平均稼動時間を表してますよね? でも、MTBFの説明には 故障が発生してから次の故障が発生するまでの時間の平均 //★2 とも書かれています。 この説明から考えると、MTBFは上の図から考えて 20分となってしまい、混乱しています。 平均なので、必ずしもイコールにはならないとは思うのですが、 ★1の説明だと、平均稼動時間ですが、 ★2の説明だと、平均稼働時間+平均修復時間 となってしまわないでしょうか?

  • 待ち行列の問題がわかりません、よろしくお願いします

    学校から待ち行列の問題が出たのですがさっぱりわからないのでどなたかわかる方よろしくお願いします。 あるスーパーに一台のレジがあり、客が代金を支払う為にレジで行列を作っている。買い物を終えレジにくる客は、ポアソン到着とし、平均到着時間間隔は60秒と20秒の場合の2通りを考える。なお、レジにおける代金支払いの所要時間を平均45秒の指数分布であるとする。平均到着時間間隔が60秒の場合と20秒の場合のそれぞれについて次の問に答えよ。 注意:単位を忘れない事、計算が出来ない場合は計算不可と記載する事 (1)客が待つ確立 (2)客が待たされない確率 (3)待っている客の人数(待ち行列の長さ)の期待値 (4)待っている客の人数とレジにてサービスを受けている客の合計人数の期待値 (5)待ち時間の期待値 (6)レジに着いてから代金を支払い出ていくまでの所用時間の期待値 さらにはレジを2台体制にした時についても答えよ。 とゆう問題です。 学校から配られたプリントを参考にしてもさっぱりとゆう感じで。 どなたかお願いします。

  • 統計学のアーラン分布について

    統計学のアーラン分布について質問です。 待ち行列理論のシュミレーションをC言語で作っていて ポアソン分布の式は分かったのですが アーラン分布の式が分かりません。 確立密度関数f(x)は平均が1/aの時に  f(x)={(at)^(k-1)/(k-1)!}*a*e^(-at)  となることまでは分かっているのですが この分布に従う値をいくつか出す方法が 分からなくなってしまいました。 文章が分かりにくくてすみません。 例えばポアソン分布なら平均1/aとして  -log(1-(random))/a (randomは0~1の乱数) として乱数の値を変えていくと できた数は全体としてポアソン分布に従っているのですが これがアーラン分布ではどのような式になるか知りたいです。 どなたか分かる方、教えてください よろしくお願いします。

  • システム科学の問題なのですが・・・

    なかなか解けなくて困っています。 できるだけ詳しい解説、解答がいただけると嬉しいです。 問.レジが一か所だけのコンビニがある。商品を持ってレジに来る客は、平均到着率がλのポアソン到着であり、レジでの会計はサービス率がμの指数分布サービスであるとする(ただし、μ>λ)時刻tにおいて、会計を待つ客の数がnである確率をPn(t)で表すとして以下の問いに答えなさい。 (1)Pn(t+⊿t)をPn(t)、Pn-1(t)、Pn+1(t)、λ、μ、⊿tを用いて表せ。 (2)P0(t+⊿t)をP0(t)、P1(t)、λ、μ、⊿tを用いて表せ。 (3)上の二式より⊿t→0の極限をとってPn(t)、P0(t)が従う微分方程式を導き、さらにPn(t)、P0(t)は定常であるとしてPnとP0の関係式を求めよ。 レジに来る客は一時間に平均80人、レジでの会計には一人平均30分かかるという。 (4)商品をもって会計に行った時、レジの空いている確率はいくらか (5)会計を待って列に並んでいる人数は平均何人か。 (6)列に並んでいる時間は一人平均何分か。 (7)レジに並び始めてから会計を終えて立ち去るまでにかかる時間は、一人平均何分か。 どうか、よろしくお願いいたします。

  • 待ち行列理論

    待ち行列理論を勉強しているのですが、いまひとつピンときません。 理解の為に、以下の例で途中式と解をご提示頂けますでしょうか。 40個の電話があり、1人につき平均3分通話します。 1時間で処理できる人数は最大何人でしょうか。 また、この問いが「1日で処理できる人数」だった場合、単純に24をかければ良いのでしょうか。 逆に1分だったら60で割れば良いのでしょうか。 宜しくお願いします。

  • 待ち行列シュミレーションのプログラム

    今現在待ち行列シュミレーションを勉強しているのですが、M/M/2モデルのプログラムをそれぞれ窓口数1(M/M/1)、窓口数3(M/M/3)のプログラムにしたいのですが上手くできません。 窓口数2のプログラムを記載します(窓口数の増減に関係ないと思われる後半のプログラムは記載してません)ので、どなたかわかる方がいましたらご教授のほうお願いします。 M/M/2 待ち行列のモデル -- ポアソン到着 => 到着時間間隔は指数分布 -- 指数サービス => サービス時間は指数分布 */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> #define N_SERVICE 2 /* 窓口数 */ #define N_USER 10000 /* 総到着人数 */ #define ARRIVAL_INTERVAL 30.0 /* 平均到着間隔*/ #define SERVICE_TIME 70.0 /* 平均サービス時間 */ double uni_random(void); /* 区間[0,1]の一様乱数 */ double exp_random(double); /* 平均値を引数にとる指数乱数*/ int main(void){ int i; /* 客番号 */ int j; /*窓口番号*/ double arrival[N_USER]={0.0} /*N人の到着時刻 */ int counter[N_USER]={0}; /*N人の利用窓口*/ int current_user[N_SERVICE]={0};/*最近の窓口利用者 */ double srv_start[N_USER]={0.0}/* N人のサービス開始時刻 */ double wait[N_USER]={0.0}; /*N人の待ち時間 */ double srv_time[N_USER]={0.0}/* N人のサービス時間 */ double srv_finish[N_USER]={0.0}; /* N人のサービス終了時刻*/ double avr_wait; /* 平均待ち時間*/ double avr_srvtime; /* 平均サービス時間  */ double avr_srvrate[N_SERVICE]={0.0}; /* 窓口の稼働率 */ /* 乱数の「種」を初期化 */ srand((unsigned)time(NULL)); /* 最初の客が到着した時刻から開始. 窓口0に入ってすぐサービス開始 */ arrival[0]=0.0; counter[0]=0; current_user[0]=0; srv_start[0]=0.0; wait[0]=0.0; srv_time[0]=exp_random(SERVICE_TIME); srv_finish[0]=srv_start[0] + srv_time[0]; /* 2人目の客が到着. 窓口0が空いていれば窓口0に、塞がっていれば窓口1に入ってすぐサービス開始 */ arrival[1]=arrival[0]+exp_random(ARRIVAL_INTERVAL); if(srv_finish[0]>arrival[1]){ counter[1]=1; current_user[1]=1; } else{ counter[1]=0; current_user[0]=1; } srv_start[1]=arrival[1]; wait[1]=0.0; srv_time[1]=exp_random(SERVICE_TIME); srv_finish[1]=srv_start[1]+srv_time[1]; for(i=2; i<N_USER; i++){ /* 客の到着時刻 = 前の客の到着時刻 + 到着間隔 */ arrival[i]=arrival[i-1]+exp_random(ARRIVAL_INTERVAL); /* 利用窓口 = 2つに窓口で早く空くほう */ if(srv_finish[current_user[1]]<srv_finish[current_user[0]]){ counter[i]=1; } else{ counter[i]=0; }

  • 確率の問題

    銀行のある窓口では、1人の客に対してサービスに要する時間は、平均4分、分散3分だそうです。 6時間で、100人以上にサービスできる確率はいくつになるかという問題なんですが、とりあえず、平均4分だから1時間あたり15人。6時間で90人ですね。分散3分というのを考えると、100人以上になる確率はいくつなんでしょうか。