This entry is for developers who want a good mental model for how a prescriptive analytics algorithm can simulate intelligent behavior. We'll focus on the intelligent behavior in the James Blog entry, since it is quite competitive with humans. Reminder: Just hit "view source" in your browser to get the code we're talking about here.

The first thing to note is that the domain of the intelligence is quite constrained and circumscribed relative to the full realm of human intellectual endeavor. This is what makes it computationally feasible to perform a "what if" analysis to "imagine" possible scenarios and determine a next best action. Here's roughly how it works. The computer's available next actions are examined and measured for their immediate benefit. Then, for each action, the response action of the opponent is measured for its immediate benefit to the opponent, and so on. Once the real benefit of each opponent move is tabulated, the value of the best opponent action is subtracted from the immediate value of a given computer move. The best computer move is determined as the highest value move resulting from the immediate benefit minus the score of the best opponent move.

One thing I like about the game Kalah is that it is really easy to explain the competitive algorithm, relative to harder games like Chess. In Chess, evaluating the immediate benefit of a move can be challenging, especially at the beginning of the game. It's not just about the value of the piece you take because many moves don't take pieces. The value of a move is often about gaining control over spaces of the board to limit the opponent's attack and defense options. But in Kalah, you get good intelligent game play from a much simpler board evaluation. The value of a move is simply a matter of how many seeds you gain by that move.

This code (at the beginning of KalahGame.scoreMove) just copies the current board, makes the proposed move for the given player, then evaluates the new board value minus the value of the old board configuration for the given player. In effect, you get the number of seeds gained for the player by the move.

That's when things get interesting. The move scoring then becomes iteratively recursive. Each valid move of the opponent is then evaluated by recursively calling the move scoring method. Like this:

The first line is just a trick to switch between player 1 and player 2 in the levels of recursion. The "beta" value is the highest scoring move of the opponent so far, so once we switch to the opponent player in the first line, the second line just sets a large negative score so that the loop will start by selecting the first available move as being a good idea. The j loop tries each move, and the if test on the succeeding line just ensures that there is a non-zero number of seeds to pick up-- in other words, it ensure the move is valid. Then, the opponent's move is scored by recursively calling KalahGame.scoreMove(). When the recursion returns, the succeeding if test checks whether the move is better than the best result so far, stored in "beta". If it is, then this move becomes the new "beta". The alpha/beta business at the end of the j loop is an optimization that can be safely ignored. Once the j loop has examined all the moves, the best opponent move score "beta" is subtracted from the immediate benefit value of the player's move.

This is how each of a player's possible moves is scored in Kalah.getBestComputerMove(): The move's immediate benefit in the number of seeds scored minus the best value obtained from a recursive lookahead of possible opponent responses that accounts for the player's responses to the opponent, and the opponents responses in kind, and so on down to the limit of the look ahead level.

The fun bit of this code is that it is used not only to determine the computer's best move, but when you ask for the "Expert Advisor" to help you, it applies exactly the same logic to *your* board position in order to determine a recommended next move for you.

To conclude, here is a small diagram to help you see what is going on.

In this example, we're near the end of the game, and Player 1 must decide whether to make move 2 or 4. With move 2, there is an immediate benefit of 4 seeds because the 1 seed lands in an empty house, allowing the player to score that seed as well as the 3 seeds in the opposing house. This seems like a good idea, but is it? Well, Player 2's moves should be examined. In the short term, Player 2 can only respond with move 5, but this spreads out the 4 seeds. If you look ahead to the end of the game, you can see that Player 2 will ultimately score all four of those seeds. But also in the recursion, it is unavoidable that Player 1 will be able to score the remaining two seeds on the top row of houses. So the net benefit to Player 1 of making move 2 is only 2 seeds: the immediate 4 seeds, minus the 4 earned by player 2 in the rest of the game, plus the 2 additional seeds that Player 1 earns in the rest of the game. Not as good as it initially looked. However, it does turn out to be better than move 4 for Player 1. The immediate move yields no seeds for Player 1. Then, in the rest of the game play, Player 2 is able to earn 7 seeds, and Player 1 only earns 3 seeds. So, if player 1 makes move 2, then the opponent gains 4 more seeds than player 1 does.

Well, that's a wrap for this explanation of the 2-party competitive algorithm known as the "Minimax" method. Hopefully you can now see that it's not real intelligence but rather just tabulation of best outcomes according to a scoring method and constrained to a set of rules for determining valid next moves. Demystified, it becomes no more surprising that the algorithm defeats humans than it is when an algorithm can beat a human at calculating the square of a 5 digit number.

Still, this is roughly what a person does. Time and again, new possibilities are "imagined" by testing "what if" this move is made or that move is made. And the algorithm does win a lot of games, which is precisely why prescriptive analytics algorithms are so valuable as expert advisors. If you take the material covered here up by an order of magnitude, you get IBM Deep Blue. Another order of magnitude, and you get IBM Watson. The sky's the limit!