生活の中のシミュレーション


  4名の職場での仕事の処理をシミュレーションしてみた。

  暇な人が、忙しい人に協力する体制とどのくらい平均処理時間に差がでるのだろうか?

  とりあえず 『非協力的な4人』という設定でシミュレーションしてみる。
  但し、1人1人は『来た仕事は真面目に』こなします。           

 条件
  1)ランダムに仕事が来る。 
  2)4名は独立に仕事をして協力するはことはない。
  3)実労働日 20日/月で固定と仮定する。
  4)8時間労働/日とする。
  5)1件あたりの処理は、3時間とする。
  6)40件/月の仕事が来るとする。

  ※下記は設定を丁度良い設定としているが、ほんの少し処理時間が増える(=手間取る)と4人分の
   仕事量に満たないのに数日後、破壊的な状態へ移行する。



仕事の閑繁シミュレート

JOB_status

  


!------初期設定1(ユーザ設定用)----------------------------------------------------------- 十進BASIC

LET Work_DAY=20 ! 15日〜22日毎日、8時間労働とし 月当たりの労働日数をだいたい20日とする(デフォルト 20日)
LET α=0.15 ! 0.15〜0.8 処理量の2割〜8割近くが最終日の3日間に集中する
! 偏りがなければ、3/20=15%になる
LET MonthEND_JOB_N=50 ! 50〜200件 月当たりの仕事の件数
LET JOB_TIME=3 ! 0.25〜5h 1件あたりの工数
LET N=4 ! 人数 1〜100人 (デフォルト 4人)
LET WT=0.1 ! 表示速度調整(デフォルト0.1秒 単位:秒)
LET MM=10 ! MM分区切りで表示(デフォルト:10分)

!――――宣言文――――――――――――――――――――――――――――
RANDOMIZE
!OPTION BASE 0
DIM JOB_BORN_TIME(N,1000) ! 仕事が発生する時間を格納する(0日〜20日まで)
DIM JOB_BORN_TIME_DAY(N,1000) ! 仕事が発生する時間(何日目)を格納する
DIM JOB_BORN_TIME_Hour(N,1000) ! 仕事が発生する時間(何時)を格納する
DIM Sum_JOB_hour(N),BK_cnt(N) ! 残り仕事量と物件番号用のカウンタ
DIM KADO(N),NON_KADO(N) ! 稼動、非稼動
!―――――――――――――――――――――――――――――――――――

!------------------------------------------------------------------------------------------
SUB ini
FOR I=1 TO N
LET BK_cnt(I)=1 ! 物件カウンタの初期設定 1番目から始める
NEXT I
END SUB
!-------------------------------------------------------------------------------------------



FOR LL=1 TO 10000
CALL ini ! 物件カウンタの初期設定 1番目から始める
PRINT "□□□□□□□□□□□□□□□□□□□□□□□□□□□";LL;"月目 □□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□"
CALL JOB_T1 ! 仕事データを発生させる
PRINT "――――――――――――――――――――――――――――――――――――――――"
CALL MAIN
NEXT LL


! ---- メインルーチン ------------------------------------------------------------------
SUB MAIN
LET Unit60=1/60 ! 単位は、hour 1時間の1/60づつ進める
FOR JJJ=0 TO 8*Work_DAY STEP Unit60 ! 分刻みで時間を経過させる 8時間×60分

FOR QT=1 TO N
IF JOB_BORN_TIME(QT,BK_cnt(QT))=<JJJ AND BK_cnt(QT)=<MonthEND_JOB_N THEN
CALL JOB_ALART1 ! 仕事が入ってきたら、 ジョブ表示1
PRINT ""
LET Sum_JOB_hour(QT)=Sum_JOB_hour(QT)+JOB_TIME
LET BK_cnt(QT)=BK_cnt(QT)+1
END IF
NEXT QT


FOR I=1 TO N
IF Sum_JOB_hour(I)=>1/60 THEN ! 減算処理
LET KADO(I)=KADO(I)+1
LET Sum_JOB_hour(I)=Sum_JOB_hour(I) - 1/60 ! <----減算処理--減算処理--減算処理
ELSE
LET NON_KADO(I)=NON_KADO(I)+1
END IF
NEXT I



IF MOD(ROUND(JJJ*60,0),MM)=0 THEN
CALL TIME_stamp ! タイムスタンプの表示

FOR QT=1 TO N
IF Sum_JOB_hour(QT)>=3 THEN
PRINT QT;"番さん:";REPEAT$("■",Sum_JOB_hour(QT)*4);" 忙しい〜!"
ELSEIF Sum_JOB_hour(QT)>=0.1 THEN
PRINT QT;"番さん:";REPEAT$("■",Sum_JOB_hour(QT)*4);" 普通"
ELSE
PRINT QT;"番さん: (−o-)ふぅ〜 余裕だ。"
END IF
! PRINT " 稼働率=";ROUND(KADO(QT)/(KADO(QT)+NON_KADO(QT))*100,2);"%"
NEXT QT

LET TOTAL_KADO=0
LET TOTAL_NON_KADO=0
FOR QT=1 TO N
IF Sum_JOB_hour(QT)>=1/60 THEN
LET TOTAL_KADO=TOTAL_KADO+1
ELSE
LET TOTAL_NON_KADO=TOTAL_NON_KADO+1
END IF
NEXT QT
PRINT "現在の稼動率=";ROUND(TOTAL_KADO/(TOTAL_KADO+TOTAL_NON_KADO)*100,2);"%"


LET ΣKADO=0
LET ΣNON_KADO=0
FOR QT=1 TO N
LET ΣKADO=ΣKADO+KADO(QT)
LET ΣNON_KADO=ΣNON_KADO+NON_KADO(QT)
NEXT QT
PRINT "累積-全体の稼動率=";ROUND(ΣKADO/(ΣKADO+ΣNON_KADO)*100,2);"%"
PRINT ""

END IF

WAIT DELAY WT
NEXT JJJ
END SUB
! ---------------------------------------------------------------------------------------



! ---------------------------以下、サブルーチン------------------------------------------
SUB TIME_stamp !タイムスタンプ タイムスタンプ タイムスタンプ タイムスタンプ
IF MOD(JJJ,8)<3 THEN
PRINT INT(JJJ/8)+1;"日目";INT(MOD(JJJ,8))+9;"時";ROUND(((JJJ-INT(JJJ))*60),0);"分"
ELSE
PRINT INT(JJJ/8)+1;"日目";INT(MOD(JJJ,8))+10;"時";ROUND(((JJJ-INT(JJJ))*60),0);"分"
END IF
END SUB


SUB JOB_ALART1 ! ジョブアラート
LET MINIT=INT((JOB_BORN_TIME_Hour(QT,BK_cnt(QT))-INT(JOB_BORN_TIME_Hour(QT,BK_cnt(QT))))*60)
IF JOB_BORN_TIME_Hour(QT,BK_cnt(QT))<3 THEN
PRINT JOB_BORN_TIME_DAY(QT,BK_cnt(QT))+1;"日目";INT(JOB_BORN_TIME_Hour(QT,BK_cnt(QT)))+9;"時";MINIT;"分: ";QT;"番さんに 今月 ";BK_cnt(QT);"件目の 仕事が来た!!---"
ELSE
PRINT JOB_BORN_TIME_DAY(QT,BK_cnt(QT))+1;"日目";INT(JOB_BORN_TIME_Hour(QT,BK_cnt(QT)))+10;"時";MINIT;"分: ";QT;"番さんに 今月 ";BK_cnt(QT);"件目の 仕事が来た!!---"
END IF
END SUB




SUB JOB_T1 ! 月末集中する処理件数を発生させる
FOR QQQ=1 TO N
FOR I=1 TO MonthEND_JOB_N
LET a=RND !0〜1の乱数を発生させる
IF a=<α THEN !0.8以下の数字の処理
LET a=(a/α)*8*3+8*(Work_DAY-3)
LET MonthEND_JOB_N_LAST= MonthEND_JOB_N_LAST+1
ELSE !0.8超えの数字の処理
LET a=(a-α)/(1-α)*(Work_DAY-3)*8
LET MonthEND_JOB_N_FAST= MonthEND_JOB_N_FAST+1

END IF

LET JOB_BORN_TIME(QQQ,I)=a
LET JOB_BORN_TIME_DAY(QQQ,I)=INT(JOB_BORN_TIME(QQQ,I)/8)
LET JOB_BORN_TIME_Hour(QQQ,I)=MOD(JOB_BORN_TIME(QQQ,I),8)
NEXT I
NEXT QQQ

PRINT "1番目のデータソート開始 ! ";TIME$
CALL SORT1
PRINT "1番目のデータソート完了! ";TIME$
END SUB



SUB SORT1
FOR J=1 TO N
! データを時間順に並べなおす
DO
LET TST=0
FOR I=2 TO MonthEND_JOB_N
IF JOB_BORN_TIME(J,I-1)>JOB_BORN_TIME(J,I) THEN
SWAP JOB_BORN_TIME(J,I-1),JOB_BORN_TIME(J,I)
LET TST=1
END IF
NEXT I
LOOP UNTIL TST=0


FOR I=1 TO MonthEND_JOB_N
LET JOB_BORN_TIME_DAY(J,I)=INT(JOB_BORN_TIME(J,I)/8)
LET JOB_BORN_TIME_Hour(J,I)=MOD(JOB_BORN_TIME(J,I),8)
NEXT I
NEXT J

END SUB


END





Math TOP