Removing Bracket type

This commit is contained in:
vandomej 2021-10-06 11:29:06 -07:00
parent 71e613c1c1
commit fb78ce77ab
2 changed files with 59 additions and 110 deletions

View file

@ -53,8 +53,7 @@ pub trait GeneticNode {
/// Used externally to wrap a node implementing the [`GeneticNode`] trait. Processes state transitions for the given node as
/// well as signal recovery. Transition states are given by [`GeneticState`]
#[derive(Debug, Serialize, Deserialize)]
pub struct GeneticNodeWrapper<T>
{
pub struct GeneticNodeWrapper<T> {
pub data: Option<T>,
state: GeneticState,
pub iteration: u64,

View file

@ -9,70 +9,83 @@ use anyhow::anyhow;
use file_linked::FileLinked;
use genetic_node::{GeneticNode, GeneticNodeWrapper};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde::Serialize;
use std::fmt::Debug;
use std::fs::File;
use std::io::ErrorKind;
use std::mem::replace;
use std::mem::swap;
use std::path::Path;
/// As the bracket tree increases in height, `IterationScaling` can be used to configure the number of iterations that
/// a node runs for.
/// Creates a tournament style bracket for simulating and evaluating nodes of type `T` implementing [`GeneticNode`].
/// These nodes are built upwards as a balanced binary tree starting from the bottom. This results in `Bracket` building
/// a separate tree of the same height then merging trees together. Evaluating populations between nodes and taking the strongest
/// individuals.
///
/// # Examples
///
/// TODO
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "enumType", content = "enumContent")]
pub enum IterationScaling {
/// Scales the number of simulations linearly with the height of the bracket tree given by `f(x) = mx` where
/// x is the height and m is the linear constant provided.
Linear(u64),
/// Each node in a bracket is simulated the same number of times.
Constant(u64),
}
impl Default for IterationScaling {
fn default() -> Self {
IterationScaling::Constant(1)
}
}
#[derive(Debug, Serialize, Deserialize)]
struct Bracket<T>
{
tree: Option<Tree<Option<GeneticNodeWrapper<T>>>>,
iteration_scaling: IterationScaling,
}
impl<T> Bracket<T>
/// [`GeneticNode`]: genetic_node::GeneticNode
pub struct Gemla<T>
where
T: GeneticNode + Serialize + Debug,
T: Serialize,
{
data: FileLinked<Option<Tree<Option<GeneticNodeWrapper<T>>>>>,
}
impl<T> Gemla<T>
where
T: GeneticNode + Serialize + DeserializeOwned + Debug,
{
pub fn new(path: &Path, overwrite: bool) -> Result<Self, Error> {
match File::open(path) {
Ok(file) => {
drop(file);
Ok(Gemla {
data: if overwrite {
FileLinked::new(Some(btree!(None)), path)?
} else {
FileLinked::from_file(path)?
},
})
}
Err(error) if error.kind() == ErrorKind::NotFound => Ok(Gemla {
data: FileLinked::new(Some(btree!(None)), path)?,
}),
Err(error) => Err(Error::IO(error)),
}
}
pub fn simulate(&mut self, steps: u64) -> Result<(), Error> {
self.data.mutate(|d| Gemla::increase_height(d, steps))?;
self.data
.mutate(|d| Gemla::process_tree(d.as_mut().unwrap()))??;
Ok(())
}
fn build_empty_tree(size: usize) -> Tree<Option<GeneticNodeWrapper<T>>> {
if size <= 1 {
btree!(None)
} else {
btree!(
None,
Bracket::build_empty_tree(size - 1),
Bracket::build_empty_tree(size - 1)
Gemla::build_empty_tree(size - 1),
Gemla::build_empty_tree(size - 1)
)
}
}
fn increase_height(&mut self, amount: u64) {
fn increase_height(tree: &mut Option<Tree<Option<GeneticNodeWrapper<T>>>>, amount: u64) {
for _ in 0..amount {
let height = self.tree.as_ref().unwrap().height();
let tree = replace(&mut self.tree, None);
drop(replace(
&mut self.tree,
Some(btree!(
let height = tree.as_ref().unwrap().height();
let temp = tree.take();
swap(
tree,
&mut Some(btree!(
None,
tree.unwrap(),
Bracket::build_empty_tree(height as usize)
temp.unwrap(),
Gemla::build_empty_tree(height as usize)
)),
));
);
}
}
@ -80,8 +93,8 @@ where
if tree.val.is_none() {
match (&mut tree.left, &mut tree.right) {
(Some(l), Some(r)) => {
Bracket::process_tree(&mut (*l))?;
Bracket::process_tree(&mut (*r))?;
Gemla::process_tree(&mut (*l))?;
Gemla::process_tree(&mut (*r))?;
let left_node = (*l).val.as_ref().unwrap().data.as_ref().unwrap();
let right_node = (*r).val.as_ref().unwrap().data.as_ref().unwrap();
@ -102,69 +115,6 @@ where
Ok(())
}
fn process(&mut self) -> Result<(), Error> {
Bracket::process_tree(self.tree.as_mut().unwrap())?;
Ok(())
}
}
/// Creates a tournament style bracket for simulating and evaluating nodes of type `T` implementing [`GeneticNode`].
/// These nodes are built upwards as a balanced binary tree starting from the bottom. This results in `Bracket` building
/// a separate tree of the same height then merging trees together. Evaluating populations between nodes and taking the strongest
/// individuals.
///
/// [`GeneticNode`]: genetic_node::GeneticNode
pub struct Gemla<T>
where T: Serialize
{
data: FileLinked<Bracket<T>>,
}
impl<T> Gemla<T>
where
T: GeneticNode + Serialize + DeserializeOwned + Debug,
{
pub fn new(path: &Path, overwrite: bool) -> Result<Self, Error> {
match File::open(path) {
Ok(file) => {
drop(file);
Ok(Gemla {
data: if overwrite {
FileLinked::new(
Bracket {
tree: Some(btree!(None)),
iteration_scaling: IterationScaling::default(),
},
path,
)?
} else {
FileLinked::from_file(path)?
},
})
}
Err(error) if error.kind() == ErrorKind::NotFound => Ok(Gemla {
data: FileLinked::new(
Bracket {
tree: Some(btree!(None)),
iteration_scaling: IterationScaling::default(),
},
path,
)?,
}),
Err(error) => Err(Error::IO(error)),
}
}
pub fn simulate(&mut self, steps: u64) -> Result<(), Error> {
self.data.mutate(|b| b.increase_height(steps))?;
self.data.mutate(|b| b.process())??;
Ok(())
}
}
#[cfg(test)]