6.00.2x学习笔记Week1 Part2
Turning data into knowledge.
Simulation
Simulation models can be classified along three dimensions:
- deterministic versus stochastic
- Deterministic simulations are completely defined by the model. Rerunning a simulation will not change the outcome. Deterministic simulations are typically used when the system being modeled is too complex to analyze analytically.
- Stochastic simulations include randomness. That means that different runs of the same simulation with the same initial conditions can generate different results.
- static versus dynamic
- discrete versus continuous
- In a discrete model, the values of the pertinent variables are enumerable for example, the integers.
- In a continuous model, they’re not enumerable.
class Location(object):
def __init__(self, x, y):
"""x and y are floats"""
self.x = x
self.y = y
def move(self, deltaX, deltaY):
"""deltaX and deltaY are floats"""
return Location(self.x + deltaX, self.y + deltaY)
def getX(self):
return self.x
def getY(self):
return self.y
def distFrom(self, other):
ox = other.x
oy = other.y
xDist = self.x - ox
yDist = self.y - oy
return (xDist**2 + yDist**2)**0.5
def __str__(self):
return '<' + str(self.x) + ', ' + str(self.y) + '>'
class Field(object):
def __init__(self):
self.drunks = {}
def addDrunk(self, drunk, loc):
if drunk in self.drunks:
raise ValueError('Duplicate drunk')
else:
self.drunks[drunk] = loc
def moveDrunk(self, drunk):
if not drunk in self.drunks:
raise ValueError('Drunk not in field')
xDist, yDist = drunk.takeStep()
currentLocation = self.drunks[drunk]
#use move method of Location to get new location
self.drunks[drunk] = currentLocation.move(xDist, yDist)
def getLoc(self, drunk):
if not drunk in self.drunks:
raise ValueError('Drunk not in field')
return self.drunks[drunk]
import random
class Drunk(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'This drunk is named ' + self.name
class UsualDrunk(Drunk):
def takeStep(self):
stepChoices =\
[(0.0,1.0), (0.0,-1.0), (1.0, 0.0), (-1.0, 0.0)]
return random.choice(stepChoices)
模拟醉汉的随机走向,建了3个class。UsualDrunk
继承Drunk
。
def walk(f, d, numSteps):
"""一个醉汉(d)在一个田里(f)走了几步(numSteps)"""
start = f.getLoc(d) # get initial location
for s in range(numSteps):
f.moveDrunk(d)
return(start.distFrom(f.getLoc(d)))
def simWalks(numSteps, numTrials):
homer = UsualDrunk('Homer')
origin = Location(0, 0)
distances = []
for t in range(numTrials):
f = Field()
f.addDrunk(homer, origin)
distances.append(walk(f, homer, numSteps))
return distances
def drunkTest(numTrials = 20):
for numSteps in [10, 100, 1000, 10000]:
distances = simWalks(numSteps, numTrials)
print 'Random walk of ' + str(numSteps) + ' steps'
print ' Mean =', sum(distances)/len(distances)
print ' Max =', max(distances), 'Min =', min(distances)
drunkTest()
给出了3个function。
random.seed(0)
可以帮助debug。
为了了解随着steps增加和distance之间的关系,我们可以用pylab把他们画出来。
def drunkTestP(numTrials = 50):
stepsTaken = [10, 100, 1000, 10000]
meanDistances = []
for numSteps in stepsTaken:
distances = simWalks(numSteps, numTrials)
meanDistances.append(sum(distances)/len(distances))
pylab.plot(stepsTaken, meanDistances)
pylab.title('Mean Distance from Origin')
pylab.xlabel('Steps Taken')
pylab.ylabel('Steps from Origin')
pylab.show()
还可以假定两种不同的走法,看距离是更远还是更近。
class ColdDrunk(Drunk):
def takeStep(self):
stepChoices =\
[(0.0,0.95), (0.0,-1.0), (1.0, 0.0), (-1.0, 0.0)]
return random.choice(stepChoices)
class EDrunk(Drunk):
def takeStep(self):
deltaX = random.random()
if random.random() < 0.5:
deltaX = -deltaX
deltaY = random.random()
if random.random() < 0.5:
deltaY = -deltaY
return (deltaX, deltaY)
Starting with abstract data types makes life easirer.
Subclassing is useful
Once basic structure in place, we can try different experiments
Plotting to get insights into trends.
Read more: