From 892a0afb547cd1489f525fb8b224d69ddd38b21f Mon Sep 17 00:00:00 2001 From: Felix Martin Date: Sun, 12 Dec 2021 20:00:03 -0500 Subject: [PATCH] Implement project 4 q1-q5. --- p4_tracking/bustersAgents.py | 26 +++++++++++- p4_tracking/inference.py | 78 +++++++++++++++++++++++++++--------- 2 files changed, 83 insertions(+), 21 deletions(-) diff --git a/p4_tracking/bustersAgents.py b/p4_tracking/bustersAgents.py index 8ad44a4..594c1b4 100644 --- a/p4_tracking/bustersAgents.py +++ b/p4_tracking/bustersAgents.py @@ -162,5 +162,27 @@ class GreedyBustersAgent(BustersAgent): livingGhostPositionDistributions = \ [beliefs for i, beliefs in enumerate(self.ghostBeliefs) if livingGhosts[i+1]] - "*** YOUR CODE HERE ***" - util.raiseNotDefined() + + def getMaxProbPos(distribution): + return max([(prob, pos) for pos, prob in distribution.items()])[1] + + closestGhostPosition = None + closestGhostDist = float("inf") + for distribution in livingGhostPositionDistributions: + ghostPosition = getMaxProbPos(distribution) + dist = self.distancer.getDistance(pacmanPosition, ghostPosition) + if dist < closestGhostDist: + closestGhostPosition = ghostPosition + closestGhostDist = dist + + if closestGhostPosition is None: + return 'Stop' + + distanceActionTuples = [ + (self.distancer.getDistance( + Actions.getSuccessor(pacmanPosition, action), + closestGhostPosition), + action) + for action in legal] + + return min(distanceActionTuples)[1] diff --git a/p4_tracking/inference.py b/p4_tracking/inference.py index 3a33c3b..0cdd0f6 100644 --- a/p4_tracking/inference.py +++ b/p4_tracking/inference.py @@ -149,17 +149,18 @@ class ExactInference(InferenceModule): pacmanPosition = gameState.getPacmanPosition() "*** YOUR CODE HERE ***" - util.raiseNotDefined() - - # Replace this code with a correct observation update - # Be sure to handle the "jail" edge case where the ghost is eaten - # and noisyDistance is None allPossible = util.Counter() - for p in self.legalPositions: - trueDistance = util.manhattanDistance(p, pacmanPosition) - if emissionModel[trueDistance] > 0: - allPossible[p] = 1.0 - + if noisyDistance is None: + # Ghost is in jail. + for p in self.legalPositions: + allPossible[p] = 0.0 + jailPosition = self.getJailPosition() + allPossible[jailPosition]= 1.0 + else: + for p in self.legalPositions: + trueDistance = util.manhattanDistance(p, pacmanPosition) + pNoisy = emissionModel[trueDistance] + allPossible[p] = pNoisy * self.beliefs[p] "*** END YOUR CODE HERE ***" allPossible.normalize() @@ -218,8 +219,18 @@ class ExactInference(InferenceModule): are used and how they combine to give us a belief distribution over new positions after a time update from a particular position. """ - "*** YOUR CODE HERE ***" - util.raiseNotDefined() + pacmanPosition = gameState.getPacmanPosition() + allPossible = util.Counter() + for pos in self.legalPositions: + allPossible[pos] = 0.0 + + for oldPos in self.legalPositions: + newPosDist = self.getPositionDistribution(self.setGhostPosition(gameState, oldPos)) + for newPos, prob in newPosDist.items(): + allPossible[newPos] += self.beliefs[oldPos] * prob + + allPossible.normalize() + self.beliefs = allPossible def getBeliefDistribution(self): return self.beliefs @@ -253,7 +264,9 @@ class ParticleFilter(InferenceModule): Storing your particles as a Counter (where there could be an associated weight with each position) is incorrect and may produce errors. """ - "*** YOUR CODE HERE ***" + numLegalPositions = len(self.legalPositions) + self.particles = [self.legalPositions[i % numLegalPositions] + for i in range(self.numParticles)] def observe(self, observation, gameState): """ @@ -283,10 +296,28 @@ class ParticleFilter(InferenceModule): distance between a particle and Pacman's position. """ noisyDistance = observation - emissionModel = busters.getObservationDistribution(noisyDistance) + + # 1) + if noisyDistance is None: + self.particles = [self.getJailPosition() + for _ in range(self.numParticles)] + return + pacmanPosition = gameState.getPacmanPosition() - "*** YOUR CODE HERE ***" - util.raiseNotDefined() + emissionModel = busters.getObservationDistribution(noisyDistance) + distribution, samples = [], [] + for particle in self.particles: + trueDistance = util.manhattanDistance(particle, pacmanPosition) + probability = emissionModel[trueDistance] + distribution.append(probability) + samples.append(particle) + + # 2) + if not [p for p in distribution if p > 0.0]: + self.initializeUniformly(gameState) + return + + self.particles = util.nSample(distribution, samples, self.numParticles) def elapseTime(self, gameState): """ @@ -303,7 +334,12 @@ class ParticleFilter(InferenceModule): a belief distribution. """ "*** YOUR CODE HERE ***" - util.raiseNotDefined() + newParticles = [] + for oldPos in self.particles: + newPosDist = self.getPositionDistribution(self.setGhostPosition(gameState, oldPos)) + newParticle = util.sample(newPosDist) + newParticles.append(newParticle) + self.particles = newParticles def getBeliefDistribution(self): """ @@ -312,8 +348,12 @@ class ParticleFilter(InferenceModule): essentially converts a list of particles into a belief distribution (a Counter object) """ - "*** YOUR CODE HERE ***" - util.raiseNotDefined() + allPossible = util.Counter() + for particle in self.particles: + allPossible[particle] += 1 + allPossible.normalize() + return allPossible + class MarginalInference(InferenceModule): """