Made bracket tree more balanced

This commit is contained in:
vandomej 2021-06-25 11:22:24 -07:00
parent 8a66fe3ee6
commit a32618da37
7 changed files with 92 additions and 106 deletions

View file

@ -2,7 +2,6 @@
/// A trait used to interact with the internal state of nodes within the genetic bracket /// A trait used to interact with the internal state of nodes within the genetic bracket
pub trait GeneticState { pub trait GeneticState {
/// Runs a simulation on the state object in order to guage it's fitness. /// Runs a simulation on the state object in order to guage it's fitness.
/// - iterations: the number of iterations (learning cycles) that the current state should simulate /// - iterations: the number of iterations (learning cycles) that the current state should simulate
/// ///

View file

@ -3,16 +3,16 @@ pub mod genetic_state;
use super::file_linked::FileLinked; use super::file_linked::FileLinked;
use super::tree; use super::tree;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use std::str::FromStr; use std::str::FromStr;
use std::string::ToString; use std::string::ToString;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(tag = "enumType", content = "enumContent")] #[serde(tag = "enumType", content = "enumContent")]
pub enum IterationScaling { pub enum IterationScaling {
Linear(u32) Linear(u32),
} }
impl Default for IterationScaling { impl Default for IterationScaling {
@ -23,105 +23,98 @@ impl Default for IterationScaling {
impl fmt::Display for IterationScaling { impl fmt::Display for IterationScaling {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", serde_json::to_string(self).expect("Unable to deserialize IterationScaling struct")) write!(
f,
"{}",
serde_json::to_string(self).expect("Unable to deserialize IterationScaling struct")
)
} }
} }
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Bracket<T> { pub struct Bracket<T> {
tree: tree::Tree<T>, tree: tree::Tree<T>,
step: u64, step: u64,
iteration_scaling: IterationScaling iteration_scaling: IterationScaling,
} }
impl<T: fmt::Display + Serialize> fmt::Display for Bracket<T> { impl<T: fmt::Display + Serialize> fmt::Display for Bracket<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", serde_json::to_string(self).expect("Unable to deserialize Bracket struct")) write!(
f,
"{}",
serde_json::to_string(self).expect("Unable to deserialize Bracket struct")
)
} }
} }
impl<T> Bracket<T> impl<T> Bracket<T>
where T: genetic_state::GeneticState + ToString + FromStr + Default + fmt::Display + DeserializeOwned + Serialize + Clone where
T: genetic_state::GeneticState
+ ToString
+ FromStr
+ Default
+ fmt::Display
+ DeserializeOwned
+ Serialize
+ Clone,
{ {
pub fn initialize(file_path: String) -> Result<FileLinked<Self>, String> pub fn initialize(file_path: String) -> Result<FileLinked<Self>, String> {
{
FileLinked::new( FileLinked::new(
Bracket Bracket {
{
tree: btree!(T::initialize()), tree: btree!(T::initialize()),
step: 0, step: 0,
iteration_scaling: IterationScaling::default() iteration_scaling: IterationScaling::default(),
} },
,file_path) file_path,
)
} }
pub fn iteration_scaling(&mut self, iteration_scaling: IterationScaling) -> &mut Self pub fn iteration_scaling(&mut self, iteration_scaling: IterationScaling) -> &mut Self {
{
self.iteration_scaling = iteration_scaling; self.iteration_scaling = iteration_scaling;
self self
} }
pub fn create_new_branch(&self, height: u64) -> tree::Tree<T> pub fn create_new_branch(&self, height: u64) -> tree::Tree<T> {
{ if height == 1 {
if height == 1
{
let mut base_node = btree!(T::initialize()); let mut base_node = btree!(T::initialize());
base_node.val.run_simulation( base_node.val.run_simulation(match self.iteration_scaling {
match self.iteration_scaling IterationScaling::Linear(x) => (x as u64) * height,
{ });
IterationScaling::Linear(x) => (x * (height as u32)).into()
}
);
btree!(base_node.val.clone()) btree!(base_node.val)
} } else {
else
{
let left = self.create_new_branch(height - 1); let left = self.create_new_branch(height - 1);
let right = self.create_new_branch(height - 1); let right = self.create_new_branch(height - 1);
let mut new_val = if left.val.get_fit_score() >= right.val.get_fit_score() let mut new_val = if left.val.get_fit_score() >= right.val.get_fit_score() {
{
left.val.clone() left.val.clone()
} } else {
else {
right.val.clone() right.val.clone()
}; };
new_val.run_simulation( new_val.run_simulation(match self.iteration_scaling {
match self.iteration_scaling IterationScaling::Linear(x) => (x as u64) * height,
{ });
IterationScaling::Linear(x) => (x * (height as u32)).into()
}
);
btree!(new_val, Some(left), Some(right)) btree!(new_val, left, right)
} }
} }
pub fn run_simulation_step(&mut self) -> &mut Self pub fn run_simulation_step(&mut self) -> &mut Self {
{
let new_branch = self.create_new_branch(self.step + 1); let new_branch = self.create_new_branch(self.step + 1);
self.tree.val.run_simulation( self.tree.val.run_simulation(match self.iteration_scaling {
match self.iteration_scaling IterationScaling::Linear(x) => ((x as u64) * (self.step + 1)),
{ });
IterationScaling::Linear(x) => ((x as u64) * (self.step + 1)).into()
}
);
let new_val = if new_branch.val.get_fit_score() >= self.tree.val.get_fit_score() let new_val = if new_branch.val.get_fit_score() >= self.tree.val.get_fit_score() {
{
new_branch.val.clone() new_branch.val.clone()
} } else {
else
{
self.tree.val.clone() self.tree.val.clone()
}; };
self.tree = btree!(new_val, new_branch, self.tree.clone());
self.tree = btree!(new_val, Some(new_branch), Some(self.tree.clone()));
self.step += 1; self.step += 1;

View file

@ -22,10 +22,7 @@ where
T: ToString, T: ToString,
{ {
pub fn new(val: T, path: String) -> Result<FileLinked<T>, String> { pub fn new(val: T, path: String) -> Result<FileLinked<T>, String> {
let result = FileLinked { let result = FileLinked { val, path };
val,
path,
};
result.write_data()?; result.write_data()?;

View file

@ -1,21 +1,19 @@
use super::super::bracket; use super::super::bracket;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr; use std::str::FromStr;
use std::string::ToString; use std::string::ToString;
use std::fmt;
use serde::{Deserialize, Serialize};
#[derive(Default, Deserialize, Serialize, Clone)] #[derive(Default, Deserialize, Serialize, Clone)]
struct TestState { struct TestState {
pub score: f64 pub score: f64,
} }
impl FromStr for TestState impl FromStr for TestState {
{
type Err = String; type Err = String;
fn from_str(s: &str) -> Result<TestState, Self::Err> fn from_str(s: &str) -> Result<TestState, Self::Err> {
{
toml::from_str(s).map_err(|_| format!("Unable to parse string {}", s)) toml::from_str(s).map_err(|_| format!("Unable to parse string {}", s))
} }
} }
@ -33,8 +31,7 @@ impl TestState {
} }
impl bracket::genetic_state::GeneticState for TestState { impl bracket::genetic_state::GeneticState for TestState {
fn run_simulation(&mut self, iterations: u64) fn run_simulation(&mut self, iterations: u64) {
{
self.score += iterations as f64; self.score += iterations as f64;
} }
@ -43,15 +40,12 @@ impl bracket::genetic_state::GeneticState for TestState {
} }
fn initialize() -> Self { fn initialize() -> Self {
TestState { TestState { score: 0.0 }
score: 0.0
}
} }
} }
#[test] #[test]
fn test_new() { fn test_new() {
let bracket = bracket::Bracket::<TestState>::initialize("./temp".to_string()) let bracket = bracket::Bracket::<TestState>::initialize("./temp".to_string())
.expect("Bracket failed to initialize"); .expect("Bracket failed to initialize");
@ -69,11 +63,13 @@ fn test_run() {
let mut bracket = bracket::Bracket::<TestState>::initialize("./temp".to_string()) let mut bracket = bracket::Bracket::<TestState>::initialize("./temp".to_string())
.expect("Bracket failed to initialize"); .expect("Bracket failed to initialize");
bracket.mutate(|b| drop(b.iteration_scaling(bracket::IterationScaling::Linear(2)))) bracket
.mutate(|b| drop(b.iteration_scaling(bracket::IterationScaling::Linear(2))))
.expect("Failed to set iteration scaling"); .expect("Failed to set iteration scaling");
for _ in 0..3 { for _ in 0..3 {
bracket.mutate(|b| drop(b.run_simulation_step())) bracket
.mutate(|b| drop(b.run_simulation_step()))
.expect("Failed to run step"); .expect("Failed to run step");
} }
@ -82,25 +78,25 @@ fn test_run() {
format!("{{\"tree\":{},\"step\":3,\"iteration_scaling\":{{\"enumType\":\"Linear\",\"enumContent\":2}}}}", format!("{{\"tree\":{},\"step\":3,\"iteration_scaling\":{{\"enumType\":\"Linear\",\"enumContent\":2}}}}",
btree!( btree!(
TestState::new(12.0), TestState::new(12.0),
Some(btree!( btree!(
TestState::new(12.0), TestState::new(12.0),
Some(btree!(TestState::new(6.0), btree!(TestState::new(6.0),
Some(btree!(TestState::new(2.0))), btree!(TestState::new(2.0)),
Some(btree!(TestState::new(2.0))))), btree!(TestState::new(2.0))),
Some(btree!(TestState::new(6.0), btree!(TestState::new(6.0),
Some(btree!(TestState::new(2.0))), btree!(TestState::new(2.0)),
Some(btree!(TestState::new(2.0))))) btree!(TestState::new(2.0)))
)), ),
Some(btree!( btree!(
TestState::new(12.0), TestState::new(12.0),
Some(btree!(TestState::new(6.0), btree!(TestState::new(6.0),
Some(btree!(TestState::new(2.0))), btree!(TestState::new(2.0)),
Some(btree!(TestState::new(2.0))))), btree!(TestState::new(2.0))),
Some(btree!(TestState::new(6.0), btree!(TestState::new(6.0),
Some(btree!(TestState::new(2.0))), btree!(TestState::new(2.0)),
Some(btree!(TestState::new(2.0))))) btree!(TestState::new(2.0))))
)) )
)) )
); );
std::fs::remove_file("./temp").expect("Unable to remove file"); std::fs::remove_file("./temp").expect("Unable to remove file");

View file

@ -4,7 +4,7 @@ use std::fs;
#[test] #[test]
fn test_mutate() -> Result<(), String> { fn test_mutate() -> Result<(), String> {
let tree = btree!(1, Some(btree!(2)), Some(btree!(3, Some(btree!(4)),))); let tree = btree!(1, btree!(2), btree!(3, btree!(4),));
let mut linked_tree = FileLinked::new(tree, String::from("test.txt"))?; let mut linked_tree = FileLinked::new(tree, String::from("test.txt"))?;
assert_eq!( assert_eq!(

View file

@ -19,14 +19,14 @@ fn test_new() {
#[test] #[test]
fn test_fmt() { fn test_fmt() {
assert_eq!( assert_eq!(
format!("{}", btree!("foo", Some(btree!("bar")),),), format!("{}", btree!("foo", btree!("bar"),),),
"{\"val\":\"foo\",\"left\":{\"val\":\"bar\",\"left\":null,\"right\":null},\"right\":null}" "{\"val\":\"foo\",\"left\":{\"val\":\"bar\",\"left\":null,\"right\":null},\"right\":null}"
); );
} }
#[test] #[test]
fn test_fmt_node() { fn test_fmt_node() {
let t = btree!(17, Some(btree!(16)), Some(btree!(12))); let t = btree!(17, btree!(16), btree!(12));
assert_eq!(Tree::fmt_node(&t.left), "16"); assert_eq!(Tree::fmt_node(&t.left), "16");
assert_eq!( assert_eq!(
Tree::fmt_node(&Some(Box::new(btree!(btree!("foo"))))), Tree::fmt_node(&Some(Box::new(btree!(btree!("foo"))))),

View file

@ -77,15 +77,16 @@ pub struct Tree<T> {
macro_rules! btree { macro_rules! btree {
($val:expr, $l:expr, $r:expr) => { ($val:expr, $l:expr, $r:expr) => {
$crate::tree::Tree::new( $crate::tree::Tree::new(
$val, $val,
$l.and_then(|l| Some(Box::new(l))), Some(Box::new($l)),
$r.and_then(|r| Some(Box::new(r)))) Some(Box::new($r)),
)
}; };
($val:expr, , $r:expr) => { ($val:expr, , $r:expr) => {
$crate::tree::Tree::new($val, None, $r.and_then(|r| Some(Box::new(r)))) $crate::tree::Tree::new($val, None, Some(Box::new($r)))
}; };
($val:expr, $l:expr,) => { ($val:expr, $l:expr,) => {
$crate::tree::Tree::new($val, $l.and_then(|l| Some(Box::new(l))), None) $crate::tree::Tree::new($val, Some(Box::new($l)), None)
}; };
($val:expr) => { ($val:expr) => {
$crate::tree::Tree::new($val, None, None) $crate::tree::Tree::new($val, None, None)