Upload folder using huggingface_hub
Browse files- Dockerfile +2 -2
- model_int8.onnx +2 -2
- neural_engine/src/main.rs +60 -3
Dockerfile
CHANGED
|
@@ -41,8 +41,8 @@ RUN mkdir -p Neurex_Engine && \
|
|
| 41 |
cp model.onnx Neurex_Engine/ || true && \
|
| 42 |
cp vocab.json Neurex_Engine/ || true
|
| 43 |
|
| 44 |
-
# Download the massive
|
| 45 |
-
RUN curl -L -o ./
|
| 46 |
|
| 47 |
# Make engines executable
|
| 48 |
RUN chmod +x Neurex_Engine/Neurex && \
|
|
|
|
| 41 |
cp model.onnx Neurex_Engine/ || true && \
|
| 42 |
cp vocab.json Neurex_Engine/ || true
|
| 43 |
|
| 44 |
+
# Download the massive model_int8.onnx.data from our model repository directly into the root folder (where model_int8.onnx is)
|
| 45 |
+
RUN curl -L -o ./model_int8.onnx.data https://huggingface.co/dpv007/Neurex-Weights/resolve/main/model_int8.onnx.data
|
| 46 |
|
| 47 |
# Make engines executable
|
| 48 |
RUN chmod +x Neurex_Engine/Neurex && \
|
model_int8.onnx
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:05535dc8a225657d15b8a4d37b0f6ffba409e183ae7e8c56eb48a2095c17b59e
|
| 3 |
+
size 163471
|
neural_engine/src/main.rs
CHANGED
|
@@ -246,10 +246,40 @@ fn evaluate_onnx(
|
|
| 246 |
(policy_map, value)
|
| 247 |
}
|
| 248 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 249 |
fn mcts_simulate(
|
| 250 |
node: &mut MCTSNode,
|
| 251 |
board: Chess,
|
| 252 |
history: &mut Vec<String>,
|
|
|
|
| 253 |
session: &mut Session,
|
| 254 |
vocab: &HashMap<String, i64>,
|
| 255 |
inv_vocab: &HashMap<i64, String>,
|
|
@@ -263,6 +293,19 @@ fn mcts_simulate(
|
|
| 263 |
return 0.0; // Draw
|
| 264 |
}
|
| 265 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 266 |
// Probe Syzygy Endgame Tablebases for positions with <= 7 pieces
|
| 267 |
if board.board().occupied().count() <= 7 {
|
| 268 |
if let Ok(wdl) = tablebases.probe_wdl(&board) {
|
|
@@ -314,6 +357,12 @@ fn mcts_simulate(
|
|
| 314 |
value = -0.95; // They are losing
|
| 315 |
}
|
| 316 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 317 |
for m in &legals {
|
| 318 |
let uci = m.to_uci(CastlingMode::Standard).to_string();
|
| 319 |
let p = policy.get(&uci).copied().unwrap_or(0.0);
|
|
@@ -355,10 +404,14 @@ fn mcts_simulate(
|
|
| 355 |
next_board.play_unchecked(&m);
|
| 356 |
history.push(best_action.clone());
|
| 357 |
|
|
|
|
|
|
|
|
|
|
| 358 |
let child_node = node.children.get_mut(&best_action).unwrap();
|
| 359 |
-
let val = mcts_simulate(child_node, next_board, history, session, vocab, inv_vocab, nn_cache, tablebases);
|
| 360 |
|
| 361 |
history.pop();
|
|
|
|
| 362 |
|
| 363 |
node.visit_count += 1;
|
| 364 |
node.value_sum += val;
|
|
@@ -371,6 +424,7 @@ fn main() {
|
|
| 371 |
let stdin = io::stdin();
|
| 372 |
let mut board = Chess::default();
|
| 373 |
let mut history_moves = vec!["<bos>".to_string()];
|
|
|
|
| 374 |
|
| 375 |
// Ensure ONNX library is set up implicitly by ort
|
| 376 |
let _ = ort::init().with_name("neural_engine").commit();
|
|
@@ -415,6 +469,8 @@ fn main() {
|
|
| 415 |
let old_history = history_moves.clone();
|
| 416 |
history_moves.clear();
|
| 417 |
history_moves.push("<bos>".to_string());
|
|
|
|
|
|
|
| 418 |
|
| 419 |
if tokens.contains(&"moves") {
|
| 420 |
let moves_idx = tokens.iter().position(|&r| r == "moves").unwrap();
|
|
@@ -423,6 +479,7 @@ fn main() {
|
|
| 423 |
if let Ok(m) = uci_move.to_move(&board) {
|
| 424 |
board.play_unchecked(&m);
|
| 425 |
history_moves.push(m_str.to_string());
|
|
|
|
| 426 |
}
|
| 427 |
}
|
| 428 |
}
|
|
@@ -524,7 +581,7 @@ fn main() {
|
|
| 524 |
let buffer = (movetime_ms as f64 * 0.05) as u128;
|
| 525 |
let mut safe_movetime = if movetime_ms > buffer { movetime_ms - buffer } else { movetime_ms };
|
| 526 |
if global_root.children.is_empty() {
|
| 527 |
-
mcts_simulate(&mut global_root, board.clone(), &mut history_moves, sess, &vocab, &inv_vocab, &mut nn_cache, &mut tablebases);
|
| 528 |
}
|
| 529 |
add_dirichlet_noise(&mut global_root, 0.3, 0.25);
|
| 530 |
|
|
@@ -534,7 +591,7 @@ fn main() {
|
|
| 534 |
let mut extended = false;
|
| 535 |
|
| 536 |
while (start_time.elapsed().as_millis() as u128) < safe_movetime {
|
| 537 |
-
mcts_simulate(&mut global_root, board.clone(), &mut history_moves, sess, &vocab, &inv_vocab, &mut nn_cache, &mut tablebases);
|
| 538 |
iter_count += 1;
|
| 539 |
|
| 540 |
// Stream UCI info and check Dynamic Time Allocation every 100 iterations
|
|
|
|
| 246 |
(policy_map, value)
|
| 247 |
}
|
| 248 |
|
| 249 |
+
fn endgame_heuristic(board: &Chess) -> f32 {
|
| 250 |
+
let mut score = 0.0;
|
| 251 |
+
let turn = board.turn();
|
| 252 |
+
|
| 253 |
+
// 1. King Centralization
|
| 254 |
+
if let Some(my_king) = board.board().king_of(turn) {
|
| 255 |
+
let file = my_king.file() as i8;
|
| 256 |
+
let rank = my_king.rank() as i8;
|
| 257 |
+
|
| 258 |
+
let dist_f = (file - 3).abs().min((file - 4).abs());
|
| 259 |
+
let dist_r = (rank - 3).abs().min((rank - 4).abs());
|
| 260 |
+
let manhattan = dist_f + dist_r;
|
| 261 |
+
|
| 262 |
+
score += (6.0 - manhattan as f32) * 0.05;
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
// 2. Passed Pawns (advanced pawns bonus)
|
| 266 |
+
let my_pawns = board.board().pawns() & board.board().by_color(turn);
|
| 267 |
+
for sq in my_pawns {
|
| 268 |
+
let r = sq.rank() as i8;
|
| 269 |
+
let relative_rank = if turn == shakmaty::Color::White { r } else { 7 - r };
|
| 270 |
+
if relative_rank >= 4 { // 5th rank or higher
|
| 271 |
+
score += (relative_rank as f32 - 3.0) * 0.05;
|
| 272 |
+
}
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
score
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
fn mcts_simulate(
|
| 279 |
node: &mut MCTSNode,
|
| 280 |
board: Chess,
|
| 281 |
history: &mut Vec<String>,
|
| 282 |
+
history_hashes: &mut Vec<u64>,
|
| 283 |
session: &mut Session,
|
| 284 |
vocab: &HashMap<String, i64>,
|
| 285 |
inv_vocab: &HashMap<i64, String>,
|
|
|
|
| 293 |
return 0.0; // Draw
|
| 294 |
}
|
| 295 |
|
| 296 |
+
// Draw Avoidance by 3-fold Repetition
|
| 297 |
+
let current_hash = board.zobrist_hash::<Zobrist64>(shakmaty::EnPassantMode::Legal).0;
|
| 298 |
+
let mut hash_count = 0;
|
| 299 |
+
for &h in history_hashes.iter() {
|
| 300 |
+
if h == current_hash {
|
| 301 |
+
hash_count += 1;
|
| 302 |
+
}
|
| 303 |
+
}
|
| 304 |
+
// If the hash appears at least twice in the history path before this node, it's a 3-fold draw!
|
| 305 |
+
if hash_count >= 2 {
|
| 306 |
+
return 0.0;
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
// Probe Syzygy Endgame Tablebases for positions with <= 7 pieces
|
| 310 |
if board.board().occupied().count() <= 7 {
|
| 311 |
if let Ok(wdl) = tablebases.probe_wdl(&board) {
|
|
|
|
| 357 |
value = -0.95; // They are losing
|
| 358 |
}
|
| 359 |
|
| 360 |
+
// Phase 3: Endgame Knowledge Heuristics (8-10 pieces)
|
| 361 |
+
if board.board().occupied().count() <= 10 {
|
| 362 |
+
value += endgame_heuristic(&board);
|
| 363 |
+
value = value.clamp(-0.99, 0.99);
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
for m in &legals {
|
| 367 |
let uci = m.to_uci(CastlingMode::Standard).to_string();
|
| 368 |
let p = policy.get(&uci).copied().unwrap_or(0.0);
|
|
|
|
| 404 |
next_board.play_unchecked(&m);
|
| 405 |
history.push(best_action.clone());
|
| 406 |
|
| 407 |
+
let next_hash = next_board.zobrist_hash::<Zobrist64>(shakmaty::EnPassantMode::Legal).0;
|
| 408 |
+
history_hashes.push(next_hash);
|
| 409 |
+
|
| 410 |
let child_node = node.children.get_mut(&best_action).unwrap();
|
| 411 |
+
let val = mcts_simulate(child_node, next_board, history, history_hashes, session, vocab, inv_vocab, nn_cache, tablebases);
|
| 412 |
|
| 413 |
history.pop();
|
| 414 |
+
history_hashes.pop();
|
| 415 |
|
| 416 |
node.visit_count += 1;
|
| 417 |
node.value_sum += val;
|
|
|
|
| 424 |
let stdin = io::stdin();
|
| 425 |
let mut board = Chess::default();
|
| 426 |
let mut history_moves = vec!["<bos>".to_string()];
|
| 427 |
+
let mut history_hashes = Vec::new();
|
| 428 |
|
| 429 |
// Ensure ONNX library is set up implicitly by ort
|
| 430 |
let _ = ort::init().with_name("neural_engine").commit();
|
|
|
|
| 469 |
let old_history = history_moves.clone();
|
| 470 |
history_moves.clear();
|
| 471 |
history_moves.push("<bos>".to_string());
|
| 472 |
+
history_hashes.clear();
|
| 473 |
+
history_hashes.push(board.zobrist_hash::<Zobrist64>(shakmaty::EnPassantMode::Legal).0);
|
| 474 |
|
| 475 |
if tokens.contains(&"moves") {
|
| 476 |
let moves_idx = tokens.iter().position(|&r| r == "moves").unwrap();
|
|
|
|
| 479 |
if let Ok(m) = uci_move.to_move(&board) {
|
| 480 |
board.play_unchecked(&m);
|
| 481 |
history_moves.push(m_str.to_string());
|
| 482 |
+
history_hashes.push(board.zobrist_hash::<Zobrist64>(shakmaty::EnPassantMode::Legal).0);
|
| 483 |
}
|
| 484 |
}
|
| 485 |
}
|
|
|
|
| 581 |
let buffer = (movetime_ms as f64 * 0.05) as u128;
|
| 582 |
let mut safe_movetime = if movetime_ms > buffer { movetime_ms - buffer } else { movetime_ms };
|
| 583 |
if global_root.children.is_empty() {
|
| 584 |
+
mcts_simulate(&mut global_root, board.clone(), &mut history_moves, &mut history_hashes, sess, &vocab, &inv_vocab, &mut nn_cache, &mut tablebases);
|
| 585 |
}
|
| 586 |
add_dirichlet_noise(&mut global_root, 0.3, 0.25);
|
| 587 |
|
|
|
|
| 591 |
let mut extended = false;
|
| 592 |
|
| 593 |
while (start_time.elapsed().as_millis() as u128) < safe_movetime {
|
| 594 |
+
mcts_simulate(&mut global_root, board.clone(), &mut history_moves, &mut history_hashes, sess, &vocab, &inv_vocab, &mut nn_cache, &mut tablebases);
|
| 595 |
iter_count += 1;
|
| 596 |
|
| 597 |
// Stream UCI info and check Dynamic Time Allocation every 100 iterations
|