aima.core.search.adversarial.AlphaBetaSearch Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aima-core Show documentation
Show all versions of aima-core Show documentation
AIMA-Java Core Algorithms from the book Artificial Intelligence a Modern Approach 3rd Ed.
package aima.core.search.adversarial;
import aima.core.search.framework.Metrics;
/**
* Artificial Intelligence A Modern Approach (3rd Ed.): Page 173.
*
*
*
* function ALPHA-BETA-SEARCH(state) returns an action
* v = MAX-VALUE(state, -infinity, +infinity)
* return the action in ACTIONS(state) with value v
*
* function MAX-VALUE(state, alpha, beta) returns a utility value
* if TERMINAL-TEST(state) then return UTILITY(state)
* v = -infinity
* for each a in ACTIONS(state) do
* v = MAX(v, MIN-VALUE(RESULT(s, a), alpha, beta))
* if v >= beta then return v
* alpha = MAX(alpha, v)
* return v
*
* function MIN-VALUE(state, alpha, beta) returns a utility value
* if TERMINAL-TEST(state) then return UTILITY(state)
* v = infinity
* for each a in ACTIONS(state) do
* v = MIN(v, MAX-VALUE(RESULT(s,a), alpha, beta))
* if v <= alpha then return v
* beta = MIN(beta, v)
* return v
*
*
*
* Figure 5.7 The alpha-beta search algorithm. Notice that these routines are
* the same as the MINIMAX functions in Figure 5.3, except for the two lines in
* each of MIN-VALUE and MAX-VALUE that maintain alpha and beta (and the
* bookkeeping to pass these parameters along).
*
* @author Ruediger Lunde
*
* @param
* Type which is used for states in the game.
* @param
* Type which is used for actions in the game.
* @param
* Type which is used for players in the game.
*/
public class AlphaBetaSearch implements
AdversarialSearch {
Game game;
private int expandedNodes;
/** Creates a new search object for a given game. */
public static AlphaBetaSearch createFor(
Game game) {
return new AlphaBetaSearch(game);
}
public AlphaBetaSearch(Game game) {
this.game = game;
}
@Override
public ACTION makeDecision(STATE state) {
expandedNodes = 0;
ACTION result = null;
double resultValue = Double.NEGATIVE_INFINITY;
PLAYER player = game.getPlayer(state);
for (ACTION action : game.getActions(state)) {
double value = minValue(game.getResult(state, action), player,
Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
if (value > resultValue) {
result = action;
resultValue = value;
}
}
return result;
}
public double maxValue(STATE state, PLAYER player, double alpha, double beta) {
expandedNodes++;
if (game.isTerminal(state))
return game.getUtility(state, player);
double value = Double.NEGATIVE_INFINITY;
for (ACTION action : game.getActions(state)) {
value = Math.max(value, minValue( //
game.getResult(state, action), player, alpha, beta));
if (value >= beta)
return value;
alpha = Math.max(alpha, value);
}
return value;
}
public double minValue(STATE state, PLAYER player, double alpha, double beta) {
expandedNodes++;
if (game.isTerminal(state))
return game.getUtility(state, player);
double value = Double.POSITIVE_INFINITY;
for (ACTION action : game.getActions(state)) {
value = Math.min(value, maxValue( //
game.getResult(state, action), player, alpha, beta));
if (value <= alpha)
return value;
beta = Math.min(beta, value);
}
return value;
}
@Override
public Metrics getMetrics() {
Metrics result = new Metrics();
result.set("expandedNodes", expandedNodes);
return result;
}
}