optimize compute_values a TON (reduce depth_of calls)... and other stuff

This commit is contained in:
Simon Gardling 2025-02-13 00:01:20 -05:00
parent ad3d31e24a
commit 9a8b674720
Signed by: titaniumtown
GPG Key ID: 9AB28AC10ECE533D

View File

@ -1,3 +1,5 @@
use either::Either;
use crate::{agent::Agent, board::Board, piece::Piece}; use crate::{agent::Agent, board::Board, piece::Piece};
#[derive(Clone)] #[derive(Clone)]
@ -137,8 +139,20 @@ impl FutureMoves {
} }
fn compute_values(&mut self) { fn compute_values(&mut self) {
// PERF! doing this filtering here previously visited moves reduces time
// spent in `depth_of` from 27.79% -> 2.9%
let mut visited = vec![false; self.arena.len()];
for depth in (0..=self.current_depth).rev() { for depth in (0..=self.current_depth).rev() {
let nodes_at_depth: Vec<usize> = (0..self.arena.len()) let nodes_at_depth: Vec<usize> = (0..self.arena.len())
.filter(|&idx| {
if visited[idx] {
false
} else {
visited[idx] = true;
true
}
})
.filter(|&idx| self.depth_of(idx) == depth) .filter(|&idx| self.depth_of(idx) == depth)
.collect(); .collect();
@ -171,21 +185,18 @@ impl FutureMoves {
} }
pub fn best_move(&self) -> Option<(usize, usize)> { pub fn best_move(&self) -> Option<(usize, usize)> {
let root_nodes = match self.current_root { (match self.current_root {
Some(root) => vec![root], Some(root) => Either::Left(vec![root].into_iter()),
None => self None => Either::Right(
.arena self.arena
.iter() .iter()
.enumerate() .enumerate()
.filter_map(|(idx, node)| node.parent.is_none().then_some(idx)) .filter_map(|(idx, node)| node.parent.is_none().then_some(idx)),
.collect(), ),
}; })
.map(|idx| &self.arena[idx])
root_nodes .max_by_key(|x| x.value)
.into_iter() .map(|x| (x.i, x.j))
.map(|idx| &self.arena[idx])
.max_by_key(|x| x.value)
.map(|x| (x.i, x.j))
} }
pub fn update_root(&mut self, i: usize, j: usize) -> bool { pub fn update_root(&mut self, i: usize, j: usize) -> bool {
@ -209,7 +220,12 @@ impl FutureMoves {
}; };
let mut retain = vec![false; self.arena.len()]; let mut retain = vec![false; self.arena.len()];
let mut stack = vec![root];
// stack is going to be AT MAXIMUM, the size of the array,
// so lets just pre-allocate it
let mut stack = Vec::with_capacity(self.arena.len());
stack.push(root);
// traverse children of the current root // traverse children of the current root
while let Some(idx) = stack.pop() { while let Some(idx) = stack.pop() {
retain[idx] = true; retain[idx] = true;