Posts Tagged ‘Harry Potter’
Expelliarmus = Bayes Filter Algorithm
In the final Harry Potter book, it is mentioned quite often that HP depends on this simple yet extremely functional spell called ‘Expelliarmus’.
I often find myself comparing Expelliarmus in the wizarding world to the Bayes Filter Algorithm in my world. It is such a simple method to give your program a little AI.
Before I go on any further, I just want to say that I didn’t invent the Bayes Filter Algorithm, I found it in this book. It is also said in this powerpoint. Additionally, for good measure, here’s a citation:
The Bayes Filter Algorithm I am using is based on the one in the book Probablistic Robotics. (Thrun, Sebastien, Wolfram Burgard, and Dieter Fox. Probablistic Robotics. Cambridge: The MIT Press, 2006.)
OK, now I think I have all of my bases covered.
So, the Bayes Filter algorithm uses Bayes Law, some initial and conditional probabilities, and the actual probabilities, to give you the final probability.
The first thing that happens is that the prior belief is calculated by adding up the multiplication of the conditional probability table and the initial beliefs.
After that, you add up the multiplication of the probability table and the prior belief.
You then find the normalizer by taking that summation and inversing it.
FINALLY, you can get the final belief when you multiply the normalizer and the number where you multiplied the probability table and the prior belief.
If you want, you can even take it a step further by putting log odds to it based on the final belief and the prior belief.
Here is a class I created in Java (in Processing) that is the Bayes Filter Algorithm:
-
class BFA {
-
-
public int numberOfStates;
-
public int numberOfSenses;
-
public float[][] probabilityTable;
-
public float[] initialBels;
-
public float[][][] conditionalProbabilityTable;
-
-
BFA(int theNumberOfStates, int theNumberOfSenses, float[][] theProbabilityTable, float[] theInitialBels, float[][][] theConditionalProbabilityTable) {
-
numberOfStates = theNumberOfStates;
-
numberOfSenses = theNumberOfSenses;
-
probabilityTable = theProbabilityTable;
-
initialBels = theInitialBels;
-
conditionalProbabilityTable = theConditionalProbabilityTable;
-
}
-
-
public void printProbabilityTable() {
-
for(int j=0; j<numberOfSenses; j++) {
-
for(int i=0; i<numberOfStates; i++) {
-
print(" " + probabilityTable[j][i] + " ");
-
}
-
println(" ");
-
}
-
-
println("\n");
-
-
for(int j=0; j<numberOfStates; j++) {
-
print(" " + initialBels[j] + " ");
-
}
-
-
println("\n");
-
-
for(int j=0; j<numberOfStates; j++) {
-
for(int i=0; i<numberOfStates; i++) {
-
print(" " + conditionalProbabilityTable[0][j][i] + " ");
-
}
-
println(" ");
-
}
-
-
println("\n");
-
-
}
-
-
public float calculateProbability(int theStateQuestioned, int sensorData, boolean logOdds, boolean logData, boolean printThem) {
-
-
float priorbel[] = new float[this.numberOfStates+1];
-
float multiplier[][] = new float[this.numberOfSenses+1][this.numberOfStates+1];
-
-
float tempResult = 0.0;
-
float normalizer = 0;
-
float summation = 0;
-
float logOddsResult;
-
-
if(logData) output.println(getTime() + "Entering Bayes Filter Algorithm");
-
-
for(int i=0; i<numberOfStates; i++) {
-
for(int j=0; j<numberOfStates; j++) {
-
tempResult += (conditionalProbabilityTable[0][i][j]*initialBels[j]);
-
}
-
priorbel[i] = tempResult;
-
if(logData) output.println(getTime() + "Prior belief calculated. priorbel[" + i + "]: " + priorbel[i]);
-
if(printThem) println("Prior bel[" + i + "]: " + priorbel[i] + " Temp result: " + tempResult);
-
tempResult = 0.0;
-
}
-
-
for(int i=0; i<numberOfStates; i++) {
-
multiplier[sensorData][i] = probabilityTable[sensorData][i]*priorbel[i];
-
summation += multiplier[sensorData][i];
-
if(logData) output.println(getTime() + "Summation and multiplier calculated. Summation: " + summation + " Multiplier: " + multiplier[sensorData][i]);
-
if(printThem) println("Summation: " + summation + " Multiplier: " + multiplier[sensorData][i]);
-
}
-
-
normalizer = pow(summation, -1);
-
if(logData) output.println(getTime() + "Normalizer and multiplied together calculated. Normalizer: " + normalizer + " Multiplied together: " + summation*normalizer);
-
if(printThem) println("Normalizer: " + normalizer);
-
if(printThem) println("Multiplied together: " + summation*normalizer);
-
-
float finalProbability = normalizer*multiplier[sensorData][theStateQuestioned];
-
float priorProbability = priorbel[theStateQuestioned];
-
-
if(logData) output.println(getTime() + "Prior probability calculated. Prior probability: " + priorProbability);
-
if(logData) output.println(getTime() + "Final probability calculated. Final probability: " + finalProbability);
-
if(printThem) println("Final probability: " + finalProbability);
-
-
if(logOdds) {
-
logOddsResult = log(finalProbability/(1-finalProbability))-log(priorProbability/(1-priorProbability));
-
if(logData) output.println(getTime() + "Log odds probability calculated. Log odds: " + logOddsResult);
-
if(logData) output.println(getTime() + "Bayes filter algorithm complete.");
-
return logOddsResult; // log base e
-
} else {
-
if(logData) output.println(getTime() + "Bayes filter algorithm complete.");
-
return finalProbability;
-
}
-
-
}
-
-
public void setNumberOfStates(int theNumber) {
-
numberOfStates = theNumber;
-
}
-
-
public int getNumberOfStates() {
-
return numberOfStates;
-
}
-
-
}
The Bayes Filter Algorithm is super handy because you can check it by hand. There are no ambiguities introduced into the algorithm. Some of the algorithms, like the Kalman Filter, use covariance in the algorithm to adjust the final belief. This is great, but definitely more tricky to calculate by hand.
I favour the Bayes Filter Algorithm right now because of its ease of use, and it gives me what I want. However, for more interesting results, the Kalman Filter would be a better way to go. If I have time at the end of this project, I’ll probably implement the Kalman Filter and use it instead of the Bayes Filter Algorithm.
