Java 阿尔法-贝塔移动排序
我有一个alpha-beta修剪的基本实现,但我不知道如何改进移动顺序。我已经读到,它可以通过浅层搜索、迭代深化或存储最佳移动到转换表来完成 对于如何在这个算法中实现这些改进,有什么建议吗Java 阿尔法-贝塔移动排序,java,algorithm,artificial-intelligence,minimax,alpha-beta-pruning,Java,Algorithm,Artificial Intelligence,Minimax,Alpha Beta Pruning,我有一个alpha-beta修剪的基本实现,但我不知道如何改进移动顺序。我已经读到,它可以通过浅层搜索、迭代深化或存储最佳移动到转换表来完成 对于如何在这个算法中实现这些改进,有什么建议吗 public double alphaBetaPruning(Board board, int depth, double alpha, double beta, int player) { if (depth == 0) { return board.evaluateBoard()
public double alphaBetaPruning(Board board, int depth, double alpha, double beta, int player) {
if (depth == 0) {
return board.evaluateBoard();
}
Collection<Move> children = board.generatePossibleMoves(player);
if (player == 0) {
for (Move move : children) {
Board tempBoard = new Board(board);
tempBoard.makeMove(move);
int nextPlayer = next(player);
double result = alphaBetaPruning(tempBoard, depth - 1, alpha,beta,nextPlayer);
if ((result > alpha)) {
alpha = result;
if (depth == this.origDepth) {
this.bestMove = move;
}
}
if (alpha >= beta) {
break;
}
}
return alpha;
} else {
for (Move move : children) {
Board tempBoard = new Board(board);
tempBoard.makeMove(move);
int nextPlayer = next(player);
double result = alphaBetaPruning(tempBoard, depth - 1, alpha,beta,nextPlayer);
if ((result < beta)) {
beta = result;
if (depth == this.origDepth) {
this.bestMove = move;
}
}
if (beta <= alpha) {
break;
}
}
return beta;
}
}
public int next(int player) {
if (player == 0) {
return 4;
} else {
return 0;
}
}
公共双字母beta调谐(棋盘、整数深度、双字母、双beta、整数播放器){
如果(深度==0){
返回板。评估板();
}
集合子项=板。生成许可移动(玩家);
如果(玩家==0){
对于(移动:儿童){
板温度板=新板(板);
tempBoard.makeMove(移动);
int nextPlayer=next(播放器);
双结果=AlphaBetaPlanning(温度板,深度-1,alpha,beta,下一层);
如果((结果>α)){
α=结果;
if(深度==此.origDepth){
this.bestMove=移动;
}
}
如果(α>=β){
打破
}
}
返回α;
}否则{
对于(移动:儿童){
板温度板=新板(板);
tempBoard.makeMove(移动);
int nextPlayer=next(播放器);
双结果=AlphaBetaPlanning(温度板,深度-1,alpha,beta,下一层);
如果((结果<β)){
β=结果;
if(深度==此.origDepth){
this.bestMove=移动;
}
}
如果(β
- 使用浅层搜索进行节点重新排序非常简单:计算
递归之前状态的每个子级的启发式值
检查它们。然后,对这些状态的值进行排序[降序]
对于最大顶点,升序对于最小顶点],并递归调用
排序列表上的算法。其思想是-如果一个状态擅长
深度较浅,也更可能处于深部状态,
如果这是真的,你会得到更多的修剪
排序应在之前进行,[在
if
和else
子句中]
for(移动:子对象){
- 存储移动也很简单-许多状态计算两次,
当您完成任何状态的计算后,将其存储[深度为
计算!它很重要!]在
HashMap
中。你要做的第一件事
在顶点上开始计算时,请检查该顶点是否已计算
计算-如果是,则返回缓存值
这是因为许多状态可以从不同的路径访问,所以
方法-您可以消除冗余计算
应该在方法的第一行进行更改[类似于if(cache.contains((新状态(棋盘,深度,玩家))返回cache.get(新状态(棋盘,深度,玩家))
][请原谅我缺乏优雅和效率-在这里仅解释一个想法]。
您还应该在每个return
语句之前添加cache.put(…)
首先,我们必须理解alpha-beta剪枝算法中移动顺序背后的原因。alpha-beta产生与minimax相同的结果,但在许多情况下,它可以更快地完成,因为它不会搜索不相关的分支
它并不总是更快,因为它不能保证修剪,如果在更坏的情况下,它根本不会修剪,并搜索与minimax完全相同的树,并且会因为a/b值记账而变得更慢。在最好的情况下(最大修剪)它允许同时搜索2倍深的树。对于随机树,它可以同时搜索4/3倍深的树
移动顺序可以通过以下两种方式实现:
你有一位领域专家,他会给你建议哪些招式更好。例如,在棋子的国际象棋推广中,用低值棋子捕获高值棋子通常是好的招式。在跳棋中,最好在一次移动中杀死更多的棋子,而不是更少的棋子,最好创建一个皇后。因此,你的招式生成功能将n更好的移动之前
通过计算深度小于1的位置(浅层搜索/迭代深化),您可以得到移动效果的启发。您计算了深度n-1处的评估,对移动进行排序,然后在深度n处进行评估
您提到的第二种方法与移动顺序无关。它与一个事实有关,即求值函数可能非常昂贵,而且许多位置需要多次求值。要绕过此方法,您可以在计算位置值后将其存储在哈希中,然后再重新使用。考虑到问题中的代码示例,您是否可以请提供一个可能的实现或排序(因此排序和递归调用都在排序列表上)?我对如何实现这一点感到困惑。这是一个非常直观的理论回答,尽管我必须学习第二部分的哈希映射。对于Python,我正在考虑使用类似`{depth:{node:score}`