dpv007 commited on
Commit
2033304
·
verified ·
1 Parent(s): 4300326

Upload folder using huggingface_hub

Browse files
neural_engine/Cargo.toml CHANGED
@@ -9,3 +9,4 @@ shakmaty = "0.26.0" # Fast chess library
9
  serde = { version = "1.0", features = ["derive"] }
10
  serde_json = "1.0"
11
  rand = "0.8.5"
 
 
9
  serde = { version = "1.0", features = ["derive"] }
10
  serde_json = "1.0"
11
  rand = "0.8.5"
12
+ rand_distr = "0.4.3"
neural_engine/src/bin/test_zobrist.rs ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ use shakmaty::{Chess, Position};
2
+ use shakmaty::zobrist::{Zobrist64, ZobristHash};
3
+
4
+ fn main() {
5
+ let board = Chess::default();
6
+ let hash = board.zobrist_hash::<Zobrist64>(shakmaty::EnPassantMode::Legal);
7
+ println!("Hash: {}", hash.0);
8
+ }
neural_engine/src/main.rs CHANGED
@@ -3,7 +3,9 @@ use std::collections::HashMap;
3
  use std::fs;
4
  use std::path::Path;
5
  use shakmaty::{Chess, Position, CastlingMode};
 
6
  use ort::session::Session;
 
7
 
8
  #[derive(Clone)]
9
  struct MCTSNode {
@@ -24,6 +26,15 @@ impl MCTSNode {
24
  }
25
  }
26
 
 
 
 
 
 
 
 
 
 
27
  fn load_vocab() -> (HashMap<String, i64>, HashMap<i64, String>) {
28
  let data = fs::read_to_string("vocab.json").expect("Unable to read vocab.json. Please run build_engine.bat first to generate it!");
29
  let vocab: HashMap<String, i64> = serde_json::from_str(&data).expect("JSON format error");
@@ -96,7 +107,7 @@ fn mcts_simulate(
96
  session: &mut Session,
97
  vocab: &HashMap<String, i64>,
98
  inv_vocab: &HashMap<i64, String>,
99
- nn_cache: &mut HashMap<String, (HashMap<String, f32>, f32)>,
100
  ) -> f32 {
101
  if board.is_game_over() {
102
  if board.is_checkmate() {
@@ -123,7 +134,7 @@ fn mcts_simulate(
123
  }
124
 
125
  // Evaluate with ONNX or Cache
126
- let cache_key = shakmaty::fen::Fen::from_position(board.clone(), shakmaty::EnPassantMode::Legal).to_string();
127
  let (policy, value) = if let Some(cached) = nn_cache.get(&cache_key) {
128
  cached.clone()
129
  } else {
@@ -201,7 +212,8 @@ fn main() {
201
 
202
  let (vocab, inv_vocab) = load_vocab();
203
 
204
- let mut nn_cache = HashMap::new();
 
205
 
206
  for line in stdin.lock().lines() {
207
  let line = line.expect("Failed to read line");
@@ -220,6 +232,7 @@ fn main() {
220
  "position" => {
221
  // position startpos moves e2e4 e7e5
222
  board = Chess::default();
 
223
  history_moves.clear();
224
  history_moves.push("<bos>".to_string());
225
 
@@ -234,6 +247,33 @@ fn main() {
234
  }
235
  }
236
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  }
238
  "go" => {
239
  let mut movetime_ms = 5000;
@@ -290,17 +330,22 @@ fn main() {
290
  }
291
 
292
  if let Some(ref mut sess) = session {
293
- let mut root = MCTSNode::new(1.0);
294
  let start_time = std::time::Instant::now();
295
  // Leave a small buffer (5% or minimum 50ms) to ensure we reply in time
296
  let buffer = (movetime_ms as f64 * 0.05) as u128;
297
  let safe_movetime = if movetime_ms > buffer { movetime_ms - buffer } else { movetime_ms };
298
  let limit = std::time::Duration::from_millis(safe_movetime as u64);
299
 
 
 
 
 
 
300
  let mut iter_count = 0;
 
301
  // Loop continuously until time expires
302
  while start_time.elapsed() < limit {
303
- mcts_simulate(&mut root, board.clone(), &mut history_moves, sess, &vocab, &inv_vocab, &mut nn_cache);
304
  iter_count += 1;
305
 
306
  // Stream UCI info every 100 iterations so !eval works
@@ -308,7 +353,7 @@ fn main() {
308
  let mut best_eval = 0.0;
309
  let mut best_visits = -1;
310
  let mut best_action = String::new();
311
- for (action, child) in &root.children {
312
  if (child.visit_count as i32) > best_visits {
313
  best_visits = child.visit_count as i32;
314
  best_action = action.clone();
@@ -327,7 +372,7 @@ fn main() {
327
  let mut best_action = String::new();
328
  let mut best_visits = -1;
329
  let mut best_eval = 0.0;
330
- for (action, child) in &root.children {
331
  if (child.visit_count as i32) > best_visits {
332
  best_visits = child.visit_count as i32;
333
  best_action = action.clone();
 
3
  use std::fs;
4
  use std::path::Path;
5
  use shakmaty::{Chess, Position, CastlingMode};
6
+ use shakmaty::zobrist::{Zobrist64, ZobristHash};
7
  use ort::session::Session;
8
+ use rand_distr::{Dirichlet, Distribution};
9
 
10
  #[derive(Clone)]
11
  struct MCTSNode {
 
26
  }
27
  }
28
 
29
+ fn add_dirichlet_noise(node: &mut MCTSNode, alpha: f32, epsilon: f32) {
30
+ if node.children.is_empty() { return; }
31
+ let dirichlet = Dirichlet::new(&vec![alpha; node.children.len()]).unwrap();
32
+ let noise = dirichlet.sample(&mut rand::thread_rng());
33
+ for (i, child) in node.children.values_mut().enumerate() {
34
+ child.prior = (1.0 - epsilon) * child.prior + epsilon * noise[i];
35
+ }
36
+ }
37
+
38
  fn load_vocab() -> (HashMap<String, i64>, HashMap<i64, String>) {
39
  let data = fs::read_to_string("vocab.json").expect("Unable to read vocab.json. Please run build_engine.bat first to generate it!");
40
  let vocab: HashMap<String, i64> = serde_json::from_str(&data).expect("JSON format error");
 
107
  session: &mut Session,
108
  vocab: &HashMap<String, i64>,
109
  inv_vocab: &HashMap<i64, String>,
110
+ nn_cache: &mut HashMap<u64, (HashMap<String, f32>, f32)>,
111
  ) -> f32 {
112
  if board.is_game_over() {
113
  if board.is_checkmate() {
 
134
  }
135
 
136
  // Evaluate with ONNX or Cache
137
+ let cache_key = board.zobrist_hash::<Zobrist64>(shakmaty::EnPassantMode::Legal).0;
138
  let (policy, value) = if let Some(cached) = nn_cache.get(&cache_key) {
139
  cached.clone()
140
  } else {
 
212
 
213
  let (vocab, inv_vocab) = load_vocab();
214
 
215
+ let mut nn_cache: HashMap<u64, (HashMap<String, f32>, f32)> = HashMap::new();
216
+ let mut global_root = MCTSNode::new(1.0);
217
 
218
  for line in stdin.lock().lines() {
219
  let line = line.expect("Failed to read line");
 
232
  "position" => {
233
  // position startpos moves e2e4 e7e5
234
  board = Chess::default();
235
+ let old_history = history_moves.clone();
236
  history_moves.clear();
237
  history_moves.push("<bos>".to_string());
238
 
 
247
  }
248
  }
249
  }
250
+
251
+ // Persist the tree if the history matches
252
+ let mut matches = true;
253
+ if old_history.len() <= history_moves.len() {
254
+ for i in 0..old_history.len() {
255
+ if old_history[i] != history_moves[i] {
256
+ matches = false;
257
+ break;
258
+ }
259
+ }
260
+ } else {
261
+ matches = false;
262
+ }
263
+
264
+ if matches {
265
+ for i in old_history.len()..history_moves.len() {
266
+ let m = &history_moves[i];
267
+ if let Some(child) = global_root.children.remove(m) {
268
+ global_root = child;
269
+ } else {
270
+ global_root = MCTSNode::new(1.0);
271
+ break;
272
+ }
273
+ }
274
+ } else {
275
+ global_root = MCTSNode::new(1.0);
276
+ }
277
  }
278
  "go" => {
279
  let mut movetime_ms = 5000;
 
330
  }
331
 
332
  if let Some(ref mut sess) = session {
 
333
  let start_time = std::time::Instant::now();
334
  // Leave a small buffer (5% or minimum 50ms) to ensure we reply in time
335
  let buffer = (movetime_ms as f64 * 0.05) as u128;
336
  let safe_movetime = if movetime_ms > buffer { movetime_ms - buffer } else { movetime_ms };
337
  let limit = std::time::Duration::from_millis(safe_movetime as u64);
338
 
339
+ if global_root.children.is_empty() {
340
+ mcts_simulate(&mut global_root, board.clone(), &mut history_moves, sess, &vocab, &inv_vocab, &mut nn_cache);
341
+ }
342
+ add_dirichlet_noise(&mut global_root, 0.3, 0.25);
343
+
344
  let mut iter_count = 0;
345
+
346
  // Loop continuously until time expires
347
  while start_time.elapsed() < limit {
348
+ mcts_simulate(&mut global_root, board.clone(), &mut history_moves, sess, &vocab, &inv_vocab, &mut nn_cache);
349
  iter_count += 1;
350
 
351
  // Stream UCI info every 100 iterations so !eval works
 
353
  let mut best_eval = 0.0;
354
  let mut best_visits = -1;
355
  let mut best_action = String::new();
356
+ for (action, child) in &global_root.children {
357
  if (child.visit_count as i32) > best_visits {
358
  best_visits = child.visit_count as i32;
359
  best_action = action.clone();
 
372
  let mut best_action = String::new();
373
  let mut best_visits = -1;
374
  let mut best_eval = 0.0;
375
+ for (action, child) in &global_root.children {
376
  if (child.visit_count as i32) > best_visits {
377
  best_visits = child.visit_count as i32;
378
  best_action = action.clone();