TEAMLAB

Human knowledge belongs to the world . -AntiTrust

(17)연산 모델:랜덤워크 시뮬레이션

MIT - Introduction to Computer Science and Programming in Python

비형식적 문제 설명에서 형식적 문제로 가는 흐름으로 공부하기

이것의 하나의 예가 최적화라고 할 수 있다.
항상 모든 것을 공식화하지 않아도 된다. 그래서 교수님은 형식적(formal)이라는 단어보다 엄밀한(rigorous)이라는 단어를 종종 사용한다고 한다.

모델 생성

거의 모든 의미있는 프로그램은 실제 세계를 모델링한 것이다. 그래서 좋은 모델을 생성하면, 모델은 우리에게 세상에 대한 통찰력을 준다.

무질서(Randomness)
  • 확률론
    세상에는 무질서한 것들이 많다. 이것들이 formal 해질 수 있도록 확률론을 적용하여 무질서를 통합해보자.
  • 데이터 감각
    세상에는 많은 데이터가 있고 이것들을 미래에 대한 통찰력 관점에서 어떻게 해석할 수 있을까?
  • 평가
    프로그램을 돌려서 결과를 얻을 때, 그 결과를 믿을 수 있는가?

상황1

상황 : 술취한 학생이 field 정 가운데에 서있다. 매 초마다 그는 어디론가 가려고 발을 딛는데, 학생이 만취되서 비틀거리기 때문에 발을 딛는 곳이 random하다. 들판은 제한되어져있다. 만약 이 학생이 500초 또는 1000초동안 그랬다면, 그가 시작한 곳에서부터 얼마나 멀리 갈 수 있을 지 예측하라.

답: 학생이 어디에 있는 지에 대한 최고의 예측은 학생이 서 있었던 곳으로부터 나올 것이고,
학생이 서 있던 곳에서부터 움직인 거리까지의 거리에 대한 최고의 예측은 0이 아닌 것이다.

비형식적인 문제인 상황1을 형식화하기 위 해결하고 싶은 문제가 무엇인지 정확하게 아는 것이 중요하다.

다시 돌아가서, 원점에서 이동되어진 거리는 시간이 갈수록 대략 늘어날까 아니면 유지될까? 어쩌면 얼마 못 갈수도 있고 아니면 같은 자리를 맴돌 수도 있을 것이다.

이 상황에 대해서 간단한 모델을 스케치해보자.

교수님이 강조하고 싶은 것은 간단한 시작 이다.
실제 문제에 관한 간단한 근사값을 가지고 시작하라. 만약 그 값들이 세상의 모델에 넣어져서 좋은 결과를 가져오지 않는다면 다른 여러 복잡성을 넣어라.
하지만 시작을 복잡한 모델로 하지 마라. 항상 간단한 모델로 시작해라.

e.g.1) 간단한 모델 - 방위
만취 학생이 딛을 걸음의 방향을 동, 서, 남, 북으로 간단하게 일반화시켜보자

Program: Random Walk Simulation

  • 시뮬레이션
    가상 세상에서 생성된 모델을 실행시켜 보는 것이다.
  • 랜덤 워크
    매우 일반적인 것으로 실제 문제를 해결하는 데 사용되곤 한다.

적절한 데이터 추상화를 해보자.

Location

만취한 학생이 어디에 있을까?

>>> class Location(object):
...     def __init__(self,x,y):
...             self.x = float(x)
...             self.y = float(y)
...     def move(self,xc,yc):
...             return Location(self.x+float(xc), self.y +float(yc))
...     def getCoord(self):
...             return self.x , self.y
...     def getDist(self,other):
...             ox,oy = other.getCoord()
...             xDist = self.x -ox
...             yDist = self.y - oy
...             return math.sqrt(xDist**2 +yDist**2)
...
컴퍼스 포인트

방향성을 참고하여 동서남북에 어디에 있는 지 보자. 물론 복잡해지면, 북서쪽, 남동쪽으로도 갈 수 있을 것이다.

>>> class CompassPt(object):
...     possibles = ('N','S','E','W')  # gloval variable
...     def __init__(self,pt):
...             if pt in possibles:
...                     self.pt = pt
...             else:
...                     raise ValueError('in CompassPt.__init__')
...     def move(self,dist):
...             if self.pt == 'N':
...                     return  (0,dist)
...             elif self.pt == 'S':
...                     return (0,-dist)
...             elif self.pt == 'E':
...                     return (dist,0)
...             elif self.pt == 'W':
...                     return (-dist,0)
...             else:
...                     raise ValueError('in CompassPt.move')
...
Field

이전의 현 위치에서 이동한 위치로 지금의 현 위치를 변경한다.

>>> class Field(object):
...     def __init__(self,drunk, loc):
...             self.drunk = drunk
...             self.loc = loc
...     def move(self,cp,dist):
...             oldLoc = self.loc
...             xc,yc = cp.move(dist) #xc= x-change
...             self.loc = oldLoc.move(xc,yc)
...     def getLoc(self):
...             return self.loc
...     def getDrunk(self):
...             return self.drunk
...
Drunk

만취 학생에 대한 클래스이다.

>>> class Drunk(object):
...     def __init__(self,name):
...             self.name = name
...     def move(self,field, time =1):
...             if field.getDrunk() != self:
...                     raise ValueError('Drunk.move called with drunk not in field.')
...             for i in range(time):
...                     pt = CompassPt(random.choice(CompassPt.possibles))
...                     field.move(pt,1)
...
실행
>>> drunk = Drunk('Homer Gimpson')
>>> for i in range(3):
...     f = Field(drunk,Location(0,0))
...     distances = performTrial(500,f)
...     plt.plot(distances)
...
[<matplotlib.lines.Line2D object at 0x000002434F9AB978>]
[<matplotlib.lines.Line2D object at 0x000002434F7D6B38>]
[<matplotlib.lines.Line2D object at 0x000002434F9ABF28>]
>>> plt.show()

위 그림의 x축은 시간이고 y축은 원점에서 부터의 거리이다.
이 그림을 보면, 시간이 갈수록 만취학생이 원점에서 부터 움직인 거리가 증가한다는 것을 볼 수 있다.
이는 처음에 예측했던 생각과는 다르다는 것을 알 수 있다.