improve parent selection
This commit is contained in:
parent
bbeb1b8b37
commit
4ec9f3cf21
@ -8,9 +8,9 @@ use std::time::Duration;
|
|||||||
fn extend_layers_test(depth: usize) {
|
fn extend_layers_test(depth: usize) {
|
||||||
let config = FutureMoveConfig {
|
let config = FutureMoveConfig {
|
||||||
max_depth: depth,
|
max_depth: depth,
|
||||||
start_pruning_at_minus: 4,
|
min_arena_depth_sub: 4,
|
||||||
top_k_children: 2,
|
top_k_children: 2,
|
||||||
up_to_mod: 4,
|
up_to_minus: 4,
|
||||||
max_arena_size: 10_000_000,
|
max_arena_size: 10_000_000,
|
||||||
};
|
};
|
||||||
let mut fut = FutureMoves::new(Piece::Black, config);
|
let mut fut = FutureMoves::new(Piece::Black, config);
|
||||||
|
|||||||
@ -14,10 +14,10 @@ impl ComplexAgent {
|
|||||||
pub const fn new(color: Piece) -> Self {
|
pub const fn new(color: Piece) -> Self {
|
||||||
const CONFIG: FutureMoveConfig = FutureMoveConfig {
|
const CONFIG: FutureMoveConfig = FutureMoveConfig {
|
||||||
max_depth: 10,
|
max_depth: 10,
|
||||||
start_pruning_at_minus: 4,
|
min_arena_depth_sub: 3,
|
||||||
top_k_children: 2,
|
top_k_children: 2,
|
||||||
up_to_mod: 4,
|
up_to_minus: 4,
|
||||||
max_arena_size: 100_000_000,
|
max_arena_size: 10_000_000,
|
||||||
};
|
};
|
||||||
Self {
|
Self {
|
||||||
color,
|
color,
|
||||||
|
|||||||
@ -26,16 +26,17 @@ pub struct FutureMoveConfig {
|
|||||||
/// Max depth of that we should try and traverse
|
/// Max depth of that we should try and traverse
|
||||||
pub max_depth: usize,
|
pub max_depth: usize,
|
||||||
|
|
||||||
/// start pruning at X depth before self.max_depth is reached
|
/// subtract this value from FutureMove.max_depth
|
||||||
/// used for pruning during tree generation before the tree is fully grown
|
/// and that would be the min depth an arena should fill for
|
||||||
pub start_pruning_at_minus: usize,
|
/// pruning to happen
|
||||||
|
pub min_arena_depth_sub: usize,
|
||||||
|
|
||||||
/// when pruning, keep the top_k # of children
|
/// when pruning, keep the top_k # of children
|
||||||
pub top_k_children: usize,
|
pub top_k_children: usize,
|
||||||
|
|
||||||
// the lower the value, the more conservative the pruning is, what level to stop pruning at?
|
// the lower the value, the more conservative the pruning is, what level to stop pruning at?
|
||||||
// a lower value allows more possible paths
|
// a lower value allows more possible paths
|
||||||
pub up_to_mod: usize,
|
pub up_to_minus: usize,
|
||||||
|
|
||||||
/// Max size of the arena, will not generate more if
|
/// Max size of the arena, will not generate more if
|
||||||
/// the arena is of that size or bigger
|
/// the arena is of that size or bigger
|
||||||
@ -71,7 +72,7 @@ impl FutureMoves {
|
|||||||
// we want to select all nodes that don't have children, or are lazy (need to maybe be regenerated)
|
// we want to select all nodes that don't have children, or are lazy (need to maybe be regenerated)
|
||||||
.filter(|&idx| {
|
.filter(|&idx| {
|
||||||
let got = &self.arena[idx];
|
let got = &self.arena[idx];
|
||||||
got.is_trimmed || got.children.is_empty()
|
!got.is_trimmed && got.winner == Winner::None && !got.tried_children
|
||||||
})
|
})
|
||||||
.filter(|&idx| self.is_connected_to_root(idx))
|
.filter(|&idx| self.is_connected_to_root(idx))
|
||||||
.collect::<Vec<usize>>()
|
.collect::<Vec<usize>>()
|
||||||
@ -84,7 +85,8 @@ impl FutureMoves {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.for_each(|node_idx| {
|
.for_each(|node_idx| {
|
||||||
self.generate_children(node_idx);
|
self.generate_children(node_idx).last();
|
||||||
|
self.arena[node_idx].tried_children = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
self.prune_bad_children();
|
self.prune_bad_children();
|
||||||
@ -109,14 +111,11 @@ impl FutureMoves {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates children for a parent (`parent`), returns an iterator it's children's indexes
|
/// Creates children for a parent (`parent`), returns an iterator it's children's indexes
|
||||||
fn generate_children(&mut self, parent_idx: usize) -> Option<impl Iterator<Item = usize>> {
|
/// Completely unchecked, the caller should be the one who tests to make sure child generation
|
||||||
|
/// hasn't already been tried on a parent
|
||||||
|
fn generate_children(&mut self, parent_idx: usize) -> impl Iterator<Item = usize> {
|
||||||
let parent = &self.arena[parent_idx];
|
let parent = &self.arena[parent_idx];
|
||||||
|
|
||||||
// early-exit if a winner for the parent already exists
|
|
||||||
if parent.winner != Winner::None {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let new_color = !parent.color;
|
let new_color = !parent.color;
|
||||||
|
|
||||||
// use [`Board::all_positions`] here instead of [`Board::possible_moves`]
|
// use [`Board::all_positions`] here instead of [`Board::possible_moves`]
|
||||||
@ -140,7 +139,7 @@ impl FutureMoves {
|
|||||||
self.set_parent_child(parent_idx, child_idx);
|
self.set_parent_child(parent_idx, child_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(new_indices)
|
new_indices
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given an index from `self.arena`, what depth is it at? 0-indexed
|
/// Given an index from `self.arena`, what depth is it at? 0-indexed
|
||||||
@ -346,7 +345,7 @@ impl FutureMoves {
|
|||||||
if self
|
if self
|
||||||
.config
|
.config
|
||||||
.max_depth
|
.max_depth
|
||||||
.saturating_sub(self.config.start_pruning_at_minus)
|
.saturating_sub(self.config.min_arena_depth_sub)
|
||||||
> self.current_depth
|
> self.current_depth
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -354,7 +353,7 @@ impl FutureMoves {
|
|||||||
|
|
||||||
for (depth, indexes) in by_depth {
|
for (depth, indexes) in by_depth {
|
||||||
// TODO! maybe update by_depth every iteration or something?
|
// TODO! maybe update by_depth every iteration or something?
|
||||||
if depth > self.current_depth.saturating_sub(self.config.up_to_mod) {
|
if depth > self.current_depth.saturating_sub(self.config.up_to_minus) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,9 +453,17 @@ impl FutureMoves {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
const FUTURE_MOVES_CONFIG: FutureMoveConfig = FutureMoveConfig {
|
||||||
|
max_depth: 1,
|
||||||
|
min_arena_depth_sub: 2,
|
||||||
|
top_k_children: 2,
|
||||||
|
up_to_minus: 0,
|
||||||
|
max_arena_size: 100,
|
||||||
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prune_tree_test() {
|
fn prune_tree_test() {
|
||||||
let mut futm = FutureMoves::new(Piece::Black, Default::default());
|
let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG);
|
||||||
|
|
||||||
futm.arena.push(Move {
|
futm.arena.push(Move {
|
||||||
i: 0,
|
i: 0,
|
||||||
@ -469,6 +476,7 @@ mod tests {
|
|||||||
self_value: 0,
|
self_value: 0,
|
||||||
color: Piece::Black,
|
color: Piece::Black,
|
||||||
is_trimmed: false,
|
is_trimmed: false,
|
||||||
|
tried_children: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
futm.update_root_idx_raw(0);
|
futm.update_root_idx_raw(0);
|
||||||
@ -508,7 +516,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn expand_layer_test() {
|
fn expand_layer_test() {
|
||||||
let mut futm = FutureMoves::new(Piece::Black, Default::default());
|
let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG);
|
||||||
futm.config.max_depth = 1;
|
futm.config.max_depth = 1;
|
||||||
|
|
||||||
futm.arena.push(Move::new(
|
futm.arena.push(Move::new(
|
||||||
@ -541,7 +549,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn depth_of_test() {
|
fn depth_of_test() {
|
||||||
let mut futm = FutureMoves::new(Piece::Black, Default::default());
|
let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG);
|
||||||
|
|
||||||
futm.arena.push(Move {
|
futm.arena.push(Move {
|
||||||
i: 0,
|
i: 0,
|
||||||
@ -554,6 +562,7 @@ mod tests {
|
|||||||
self_value: 0,
|
self_value: 0,
|
||||||
color: Piece::Black,
|
color: Piece::Black,
|
||||||
is_trimmed: false,
|
is_trimmed: false,
|
||||||
|
tried_children: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
futm.update_root_idx_raw(0);
|
futm.update_root_idx_raw(0);
|
||||||
@ -587,7 +596,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn by_depth_test() {
|
fn by_depth_test() {
|
||||||
let mut futm = FutureMoves::new(Piece::Black, Default::default());
|
let mut futm = FutureMoves::new(Piece::Black, FUTURE_MOVES_CONFIG);
|
||||||
|
|
||||||
futm.arena.push(Move {
|
futm.arena.push(Move {
|
||||||
i: 0,
|
i: 0,
|
||||||
@ -600,6 +609,7 @@ mod tests {
|
|||||||
self_value: 0,
|
self_value: 0,
|
||||||
color: Piece::Black,
|
color: Piece::Black,
|
||||||
is_trimmed: false,
|
is_trimmed: false,
|
||||||
|
tried_children: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
futm.update_root_idx_raw(0);
|
futm.update_root_idx_raw(0);
|
||||||
|
|||||||
@ -22,6 +22,9 @@ pub struct Move {
|
|||||||
/// Indices of this Move's Children
|
/// Indices of this Move's Children
|
||||||
pub children: Vec<usize>,
|
pub children: Vec<usize>,
|
||||||
|
|
||||||
|
/// Has this [`Move`] already attempted to create children?
|
||||||
|
pub tried_children: bool,
|
||||||
|
|
||||||
/// Value of this move (including children)
|
/// Value of this move (including children)
|
||||||
pub value: Option<i128>,
|
pub value: Option<i128>,
|
||||||
|
|
||||||
@ -52,6 +55,7 @@ impl Move {
|
|||||||
color,
|
color,
|
||||||
is_trimmed: false,
|
is_trimmed: false,
|
||||||
self_value: 0,
|
self_value: 0,
|
||||||
|
tried_children: false,
|
||||||
};
|
};
|
||||||
m.self_value = m.compute_self_value(agent_color);
|
m.self_value = m.compute_self_value(agent_color);
|
||||||
m
|
m
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user