소프트웨어/MATLAB

텀프로젝트] 몬테카를로 시뮬레이션_맥도날드 시뮬레이션.monte carlo simulation.MATLAB

cs만두 2012. 10. 25. 16:10

시작.

 

 

몬테카를로 시뮬레이션(Monte Carlo Simulation) 이란?

 수학적인 확률상황이 아닌, 실 생활에서 확률로 표현이 불확실한 상황에서 의사결정을 목적으로 여러번의 시뮬레이션을 통해 확률적 시스템의 모의 실험에 적용되는 절차이다.

 쉽게 말해서 여러번 실험해서 그 결과에 대한 표준편차 및 평균을 구하는 절차를 말한다.

 

 

 

 

우리 조는 이번 프로젝트에서 다음과 같은 관찰을 시행했다.

 

 

 

1. 토요일 손님이 많은 런치 타임 시간에 실제 맥도날드에 가서 한시간동안 관찰을 하였다.

2. 손님의 입장 분포 및 주문 매뉴 분포를 기록하였다.

3. 관찰된 데이터를 통해 우선 전체적인 확률 분포를 그려내었다.

 

 

 

 

 

 

     
 

 <1-1.측정한 DATA의 분포. 고객은 한팀당 1~8명까지 인원이 분포한다>

 

 

 

 

 

실제 기록한 측정 DATA와 같이 팀 인원수는 정규 분포를 따른다.

2명 1명이 가장 평균에서 가까운 값에 위치하고 3,4는 약간 멀리, 그리고 5~8은 거의 확률이 없었다.

이런 분석에 따라 우리는 MATLAB을 이용해 다음과 같은 분포를 만들었다.

 

 

 

 

 

     
   

 

 
 

 <1-2.MATLAB으로 코딩한 분포>

 

 

 

 

 1-1의 실제 데이터와 1-2의 프로그램된 데이터를 비교해보자.

0~4,6는 정규분포의 확률에 맞도록 정규분포 랜덤 함수인 randn()함수를 사용하여 범위를 지정 해주었다.

그리고 실제 측정 데이터의 도수가 0이거나 아주 작은 확률을 가진 데이터는 균일분포 rand()함수를 사용하여 지정 해주었다.

그결과 실제 데이터와 유사한 프로그램을 만들 수 있었다.

 

 

 

     
   

 

 
 

 <1-3. 매뉴별 판매 선호도>

 

 

 

위와 같은 방법으로 인기 매뉴 top15를 정하였다.

역시 가장 인기있는 매뉴 순으로 정규 분포를 따르고 여러번 데이터를 생성하여도 유사한 확률로 데이터가 생성된다.

 

 

 

 

시뮬레이션에서 가장 중요한 random DATA를 차지하는 부분은 위의 두 부분인것 같다.

이외에 그룹간 입장 시간차, 매뉴별 완성시간, 등의 다른 RANDOM DATA들은 관찰한 확률을 토대로 위와 비슷하게 프로그래밍 하였다. 모두 정규분포RANDN과 균일분포 RAND를 적절히 섞어서 생성하였다.(생략)

 

 

 

 

 

프로그램에서는 다음과 같은 조건을 달아야 했다.

1.카운터는 최소3개에서 8개까지 조절해서 적용 할 수 있어야 한다.

2. 각 카운터의 알바생은 45분 노동, 5분 휴식을 원칙으로 하여야 한다.

3. 만약 휴식 카운터가 있을시 서있는 손님을 해결 해야한다.

4. 줄이 꽉찼을시 OUT시키고 out count를 올린다.

5. 12:05부터 12:30분은 Peak Time으로써 미칠듯이 손님이 밀려온다

등등

 

 

다음으로는 대표적인 함수들의 알고리즘을 소개한다.

 

 

 

 첫번째로 들어온 손님의 줄을 정해주는 Counter_line.m파일이다.

 

동작 원리

 

손님이 들어오게되면 휴식 카운터를 검색, 카운터가 휴식시 휴식 줄의 손님은 우선순위 앞 줄 부터 나머지 줄의 최소줄을 검색하고 모두 이동한다.

휴식 카운터가 없는 조건이라면 바로 최소 줄을 검색하고 자리배치 or OUT시킨다.

 

 

 두번째로는 첫줄 손님이 주문을 하는 Order(t)함수이다.

 

동작원리

 

손님은 주문하는데 총 25초 정도가 걸린다.

주문시 해당 카운터가 휴식이 되면 min카운터로 이동.

주문시 현재시간,메뉴 완성시간, 인원정보, 메뉴정보들을 menu_rest_time이라는 (nx11)MATRIX에 저장 시킨 후 줄에서 빠지고 대기한다.

이때, 주문시간이 더 뒤에서 했음에도 불구하고 처리시간이 적은 메뉴를 고른 경우 주문이 먼저 나와야 하기 때문에 매 주문시 배열내 행기준 재 배열을 해준다.

 

 

  세번째로는 주문이 완성 됬을시 대기중인 손님이 메뉴를 수령해 가는 Pick_menu()함수이다.

 

동작원리

 

매 time마다 이 함수는 실행되고 완성시간과 현재시간이 맞는 그룹이 있으면 매뉴를 수령시킨다.

이때, 수령그룹 정보는 Sell_list라는 (n*11)MATRIX로 넘겨지고, menu_rest_time의 원 정보는 삭제된다.

그리고 menu_rest_time은 재정렬된다

 

 

 

큼직한 알고리즘은 위와 같았다.

이때 가장 문제가 됬던게, 분명히 해당 시간에 한 그룹이 주문을 수령 해 갔으나 , 저장된 menu_lest_time을 보면 시간이 지났음에도 불구하고 수령해가지 않은 손님들이 간혹 발생했다.

곰곰히 생각해본 결과 다음과 같은 사실을 발견했다.

 

 

 

 

 

1.이 프로그램은 1초 단위로 동작 하기 때문에 주문완성 시간이 .x초 단위로 내려가면 연산을 받아 들이지 못한다.

->ceil혹은 floor 함수로 해결하였다.

 

2. 1의 문제를 해결했어도 계속 수령을 하지 않는 그룹들이 발견되었다. 이 문제는 단위 시간당 한번의 수령만 허용 하였기 때문이었다.

->다음과 같은 반복문을 만들어서 해결 하였다.

 

 

 

     
   

 

 
 

 <2번 문제를 해결>

 

 

 

 

위와 같은 방법으로 해결하였다.

일단 단위시간의 첫 수령자는 수령시간 조건만 맞으면 수령 하게 만들었다.

이때, Pick_menu(4번째줄)내에서 수령그룹은 Sell_list로 정보가 옮겨지게 된다.

반복문을 돌면서 현제 들어온 sell_list의 시간과 동일한 그룹들을 menu_rest_time에서 검색하게 된다.

소스에서는 구현하지 않았지만, 반복문 내에서 sell_list의 최근 내용과 menu_rest_time의 검색행의 값이 다를경우 바로 break;를 넣었더라면 프로그램이 더 빨라지지 않았을까 생각된다.

(아무래도 menu_rest_time을 거의 다 검색 하다보니 bigO가..)

 

 

 

 

 

여기서 자세한 코드는 설명하지 않았으나 프로그램을 완성시키는데 상당히 애를 먹었다.

ㅠㅠㅠ

 

 

 

 

 작동화면은 다음과 같다.

처음에는 소스코드로 짜고 텍스트 애니매이션으로 만들고나서

GUI에 적용 시켰다.

동영상 맨 마지막과 같이 확률 분포를 이루게 된다.

 

1초~3600초까지가 한번의 시뮬레이션이다.

프로그램에 달린 추가 기능을 이용해 자신이 원하는만큼 시뮬레이션을 돌릴 수 있고 그에 관한 확률정보들도 얻을 수 있다.

끗!