Я создаю подключение 4 Negamax AI/двигатель в JavaScript и хочу сделать его как можно быстрее, то есть ищет наибольшую глубину за кратчайший момент. Вот текущий подход и внедренные стратегии: < /p>
[*] Использование 2 32-битных битбордов для каждого игрока, поскольку JS не имеет 64-битной версии, а Bigint-это медленнее: this.bitoards = {1: [0, 0], 2: [0, 0]}; // Внизу 32 бит, 10 лучших битов .
[*] Негамакс двигатель для рекурсивного прохождения ходов.
[*] Альфа/бета -обрезка.
Показанные движения в соответствии с непосредственными победами сначала, а затем, как и в центре, сортируют. Не поиск уже поисковых позиций. Бенчмаркинг выполняется в соответствии с блогом Pascal Pons с использованием "test_l2_r1", и результат такого в моем текущем состоянии: < /p>
Total cases: 1 000
Total nodes evaluated: 76 571 560
Average nodes per case: 76 572
Total time: 00:00:40.299
Average time per case: 00:00:00.040
Nodes per second: 1 900 086
< /code>
узлы в секунду находятся где -то от 2 до 4 миллионов в зависимости от текущего состояния моих компьютеров. Я думаю, что это прилично для JS, но моя главная проблема заключается в том, что я получаю примерно в 10-100 раз больше узлов, чем в блоге с теми же реализованными стратегиями. Для Connect 4. < /li>
Лучшая оценка, например, с, например, 3 в ряду, но это слишком медленно и, кажется, не улучшает обрезку. Какие стратегии могут работать, кроме того, что я попробовал?import { COLS, ROWS } from '../utils/constants.js';
let tt;
const boardSize = COLS * ROWS;
const CENTER_ORDER = [3, 2, 4, 1, 5, 0, 6];
// TT flags semantics
const FLAG_EXACT = 1;
const FLAG_LOWER = 2; // lower bound: true score >= stored score
const FLAG_UPPER = 3; // upper bound: true score = beta) return { score, flag };
if (flag === FLAG_UPPER && score = ROWS) continue;
board.makeMove(col);
if (board.checkWin()) {
board.unmakeMove();
return [col]; // Immediate win
}
board.unmakeMove();
moves.push(col);
}
return moves;
}
// Negamax
export function negamax(board, depth, alpha, beta) {
let nodes = 1;
const originalAlpha = alpha;
const cached = tt.get(board.zobristHash, depth, alpha, beta);
if (cached) {
return { score: cached.score, nodes: 1, move: null };
}
// Terminal checks
if (board.checkWin()) {
return { score: Math.ceil(board.moveCount / 2) - 22, nodes, move: null };
} else if (board.moveCount >= boardSize || depth === 0) {
return { score: 0, nodes, move: null };
}
let bestScore = -100;
let bestMove = null;
let flag = FLAG_UPPER;
for (const col of getOrderedMoves(board)) {
board.makeMove(col);
const child = negamax(board, depth - 1, -beta, -alpha);
board.unmakeMove();
nodes += child.nodes;
const score = -child.score;
if (score >= beta) {
bestScore = score;
bestMove = col;
flag = FLAG_LOWER;
break;
}
if (score > bestScore) {
bestScore = score;
bestMove = col;
}
if (score > alpha) alpha = score;
}
if (bestScore = beta) flag = FLAG_LOWER;
else flag = FLAG_EXACT;
tt.put(board.zobristHash, bestScore, depth, flag);
return { score: bestScore, nodes, move: bestMove };
}
// Entry point
export function findBestMove(board, depth) {
tt = new TranspositionTable();
const result = negamax(board, depth, -100, 100);
return { move: result.move, score: result.score, nodes: result.nodes };
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... javascript
Улучшения производительности для подключения 4 двигателя в JavaScript ⇐ Javascript
Форум по Javascript
1757498233
Anonymous
Я создаю подключение 4 Negamax AI/двигатель в JavaScript и хочу сделать его как можно быстрее, то есть ищет наибольшую глубину за кратчайший момент. Вот текущий подход и внедренные стратегии: < /p>
[*] Использование 2 32-битных битбордов для каждого игрока, поскольку JS не имеет 64-битной версии, а Bigint-это медленнее: this.bitoards = {1: [0, 0], 2: [0, 0]}; // Внизу 32 бит, 10 лучших битов .
[*] Негамакс двигатель для рекурсивного прохождения ходов.
[*] Альфа/бета -обрезка.
Показанные движения в соответствии с непосредственными победами сначала, а затем, как и в центре, сортируют. Не поиск уже поисковых позиций. Бенчмаркинг выполняется в соответствии с блогом Pascal Pons с использованием "test_l2_r1", и результат такого в моем текущем состоянии: < /p>
Total cases: 1 000
Total nodes evaluated: 76 571 560
Average nodes per case: 76 572
Total time: 00:00:40.299
Average time per case: 00:00:00.040
Nodes per second: 1 900 086
< /code>
узлы в секунду находятся где -то от 2 до 4 миллионов в зависимости от текущего состояния моих компьютеров. Я думаю, что это прилично для JS, но моя главная проблема заключается в том, что я получаю примерно в 10-100 раз больше узлов, чем в блоге с теми же реализованными стратегиями. Для Connect 4. < /li>
Лучшая оценка, например, с, например, 3 в ряду, но это слишком медленно и, кажется, не улучшает обрезку. Какие стратегии могут работать, кроме того, что я попробовал?import { COLS, ROWS } from '../utils/constants.js';
let tt;
const boardSize = COLS * ROWS;
const CENTER_ORDER = [3, 2, 4, 1, 5, 0, 6];
// TT flags semantics
const FLAG_EXACT = 1;
const FLAG_LOWER = 2; // lower bound: true score >= stored score
const FLAG_UPPER = 3; // upper bound: true score = beta) return { score, flag };
if (flag === FLAG_UPPER && score = ROWS) continue;
board.makeMove(col);
if (board.checkWin()) {
board.unmakeMove();
return [col]; // Immediate win
}
board.unmakeMove();
moves.push(col);
}
return moves;
}
// Negamax
export function negamax(board, depth, alpha, beta) {
let nodes = 1;
const originalAlpha = alpha;
const cached = tt.get(board.zobristHash, depth, alpha, beta);
if (cached) {
return { score: cached.score, nodes: 1, move: null };
}
// Terminal checks
if (board.checkWin()) {
return { score: Math.ceil(board.moveCount / 2) - 22, nodes, move: null };
} else if (board.moveCount >= boardSize || depth === 0) {
return { score: 0, nodes, move: null };
}
let bestScore = -100;
let bestMove = null;
let flag = FLAG_UPPER;
for (const col of getOrderedMoves(board)) {
board.makeMove(col);
const child = negamax(board, depth - 1, -beta, -alpha);
board.unmakeMove();
nodes += child.nodes;
const score = -child.score;
if (score >= beta) {
bestScore = score;
bestMove = col;
flag = FLAG_LOWER;
break;
}
if (score > bestScore) {
bestScore = score;
bestMove = col;
}
if (score > alpha) alpha = score;
}
if (bestScore = beta) flag = FLAG_LOWER;
else flag = FLAG_EXACT;
tt.put(board.zobristHash, bestScore, depth, flag);
return { score: bestScore, nodes, move: bestMove };
}
// Entry point
export function findBestMove(board, depth) {
tt = new TranspositionTable();
const result = negamax(board, depth, -100, 100);
return { move: result.move, score: result.score, nodes: result.nodes };
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79760710/performance-enhancements-to-connect-4-engine-in-javascript[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия