Simulating actual bracket.
This commit is contained in:
parent
de22c5ddc5
commit
5990664573
10 changed files with 194 additions and 98 deletions
|
@ -6,6 +6,7 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
uuid = { version = "0.7", features = ["serde", "v4"] }
|
uuid = { version = "0.7", features = ["serde", "v4"] }
|
||||||
clap = { version = "~2.27.0", features = ["yaml"] }
|
clap = { version = "~2.27.0", features = ["yaml"] }
|
||||||
toml = "0.5.8"
|
toml = "0.5.8"
|
||||||
|
|
7
gemla/src/bracket/genetic_state.rs
Normal file
7
gemla/src/bracket/genetic_state.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
pub trait GeneticState {
|
||||||
|
fn run_simulation(&mut self, iterations: u32);
|
||||||
|
|
||||||
|
fn get_fit_score(&self) -> f64;
|
||||||
|
|
||||||
|
fn initialize() -> Self;
|
||||||
|
}
|
|
@ -1,75 +1,91 @@
|
||||||
mod state;
|
pub mod genetic_state;
|
||||||
|
|
||||||
use super::file_linked::FileLinked;
|
use super::file_linked::FileLinked;
|
||||||
use super::tree;
|
use super::tree;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use uuid::Uuid;
|
use std::string::ToString;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
impl tree::Tree<Uuid> {
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub fn run_simulation(&self) {
|
#[serde(tag = "enumType", content = "enumContent")]
|
||||||
println!("================================");
|
pub enum IterationScaling {
|
||||||
println!("Running simulation for node: {}", self.val);
|
Linear(u32)
|
||||||
println!(
|
}
|
||||||
"With children {} and {}\n",
|
|
||||||
tree::Tree::fmt_node(&self.left),
|
impl Default for IterationScaling {
|
||||||
tree::Tree::fmt_node(&self.right)
|
fn default() -> Self {
|
||||||
|
IterationScaling::Linear(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for IterationScaling {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", serde_json::to_string(self).expect("Unable to deserialize IterationScaling struct"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct Bracket<T> {
|
||||||
|
tree: tree::Tree<T>,
|
||||||
|
step: u32,
|
||||||
|
iteration_scaling: IterationScaling
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Display + Serialize> fmt::Display for Bracket<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", serde_json::to_string(self).expect("Unable to deserialize Bracket struct"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Bracket<T>
|
||||||
|
where T: genetic_state::GeneticState + ToString + FromStr + Default + fmt::Display + DeserializeOwned + Serialize + Clone
|
||||||
|
{
|
||||||
|
pub fn initialize(file_path: String) -> Result<FileLinked<Self>, String>
|
||||||
|
{
|
||||||
|
FileLinked::new(
|
||||||
|
Bracket
|
||||||
|
{
|
||||||
|
tree: btree!(T::initialize()),
|
||||||
|
step: 0,
|
||||||
|
iteration_scaling: IterationScaling::default()
|
||||||
|
}
|
||||||
|
,file_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iteration_scaling(&mut self, iteration_scaling: IterationScaling) -> &mut Self
|
||||||
|
{
|
||||||
|
self.iteration_scaling = iteration_scaling;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_simulation_step(&mut self) -> &mut Self
|
||||||
|
{
|
||||||
|
self.tree.val.run_simulation(
|
||||||
|
match self.iteration_scaling
|
||||||
|
{
|
||||||
|
IterationScaling::Linear(x) => x
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
let mut new_branch = btree!(T::initialize());
|
||||||
|
new_branch.val.run_simulation(
|
||||||
// pub struct Bracket {
|
match self.iteration_scaling
|
||||||
// tree: tree::Tree,
|
{
|
||||||
// directory: String
|
IterationScaling::Linear(x) => x * (self.step + 1)
|
||||||
// }
|
}
|
||||||
|
);
|
||||||
/// Constructs a tree with a given height while simultaneously running a simulation on each node.
|
|
||||||
fn build_tree(h: u32) -> Option<tree::Tree<Uuid>> {
|
self.tree = btree!(
|
||||||
// Recursively building a tree and running the simulation after wards to ensure a bottom-up
|
self.tree.val.clone(),
|
||||||
// execution order.
|
Some(self.tree.clone()),
|
||||||
if h != 0 {
|
Some(new_branch)
|
||||||
let tree = btree!(
|
);
|
||||||
Uuid::new_v4(),
|
self.step += 1;
|
||||||
build_tree(h - 1),
|
|
||||||
build_tree(h - 1));
|
self
|
||||||
tree.run_simulation();
|
|
||||||
Some(tree)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates a bracket tree and runs simulation against each node.
|
|
||||||
///
|
|
||||||
/// TODO: Explain reasoning for bracket system against genetic algorithm.
|
|
||||||
pub fn run_bracket() {
|
|
||||||
let mut height = 1;
|
|
||||||
let mut tree = FileLinked::new(
|
|
||||||
build_tree(height).expect("Error getting result from build_tree"),
|
|
||||||
"for_tests",
|
|
||||||
)
|
|
||||||
.expect("Unable to create file linked object from tree");
|
|
||||||
|
|
||||||
// Building tree one node at a time, appending to the top.
|
|
||||||
loop {
|
|
||||||
println!("=========================================");
|
|
||||||
println!("Running bracket...");
|
|
||||||
height += 1;
|
|
||||||
tree.replace(btree!(
|
|
||||||
Uuid::new_v4(),
|
|
||||||
Some(tree.readonly().clone()),
|
|
||||||
build_tree(height)
|
|
||||||
))
|
|
||||||
.expect("Error building up tree node");
|
|
||||||
tree.readonly().run_simulation();
|
|
||||||
|
|
||||||
if height == 3 {
|
|
||||||
println!("{}\n\n", tree);
|
|
||||||
let s = format!("{}", tree);
|
|
||||||
println!("{}\n\n", s);
|
|
||||||
let tree2: tree::Tree<Uuid> = tree::Tree::from_str(&s).unwrap();
|
|
||||||
println!("{}\n\n", tree2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
// use uuid::Uuid;
|
|
||||||
// use std::fmt;
|
|
||||||
|
|
||||||
// pub struct State {
|
|
||||||
// id: Uuid
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl fmt::Display for State {
|
|
||||||
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
// write!(f, "{}", self.id)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn create(id: &Uuid) -> State {
|
|
||||||
// State {
|
|
||||||
// id: id.clone()
|
|
||||||
// }
|
|
||||||
// }
|
|
|
@ -21,10 +21,10 @@ impl<T> FileLinked<T>
|
||||||
where
|
where
|
||||||
T: ToString,
|
T: ToString,
|
||||||
{
|
{
|
||||||
pub fn new(val: T, path: &str) -> Result<FileLinked<T>, String> {
|
pub fn new(val: T, path: String) -> Result<FileLinked<T>, String> {
|
||||||
let result = FileLinked {
|
let result = FileLinked {
|
||||||
val,
|
val,
|
||||||
path: String::from(path),
|
path,
|
||||||
};
|
};
|
||||||
|
|
||||||
result.write_data()?;
|
result.write_data()?;
|
||||||
|
@ -32,7 +32,7 @@ where
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_data(&self) -> Result<(), String> {
|
fn write_data(&self) -> Result<(), String> {
|
||||||
let mut file = fs::OpenOptions::new()
|
let mut file = fs::OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
|
|
|
@ -31,7 +31,6 @@ fn main() {
|
||||||
Ok(m) if m.is_dir() => {
|
Ok(m) if m.is_dir() => {
|
||||||
println!("{} is a valid directory!", directory);
|
println!("{} is a valid directory!", directory);
|
||||||
println!("Building tree for {}.", directory);
|
println!("Building tree for {}.", directory);
|
||||||
bracket::run_bracket();
|
|
||||||
}
|
}
|
||||||
Ok(_) => println!("{} is not a valid directory!", directory),
|
Ok(_) => println!("{} is not a valid directory!", directory),
|
||||||
_ => println!("{} does not exist!", directory),
|
_ => println!("{} does not exist!", directory),
|
||||||
|
|
|
@ -1 +1,93 @@
|
||||||
|
use super::super::bracket;
|
||||||
|
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::string::ToString;
|
||||||
|
use std::fmt;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Default, Deserialize, Serialize, Clone)]
|
||||||
|
struct TestState {
|
||||||
|
pub score: f64
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for TestState
|
||||||
|
{
|
||||||
|
type Err = String;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<TestState, Self::Err>
|
||||||
|
{
|
||||||
|
toml::from_str(s).map_err(|_| format!("Unable to parse string {}", s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for TestState {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.score)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestState {
|
||||||
|
fn new(score: f64) -> TestState {
|
||||||
|
TestState { score: score }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl bracket::genetic_state::GeneticState for TestState {
|
||||||
|
fn run_simulation(&mut self, iterations: u32)
|
||||||
|
{
|
||||||
|
self.score += iterations as f64;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_fit_score(&self) -> f64 {
|
||||||
|
self.score
|
||||||
|
}
|
||||||
|
|
||||||
|
fn initialize() -> Self {
|
||||||
|
TestState {
|
||||||
|
score: 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_new() {
|
||||||
|
|
||||||
|
let bracket = bracket::Bracket::<TestState>::initialize("./temp".to_string())
|
||||||
|
.expect("Bracket failed to initialize");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
format!("{}", bracket),
|
||||||
|
format!("{{\"tree\":{},\"step\":0,\"iteration_scaling\":{{\"enumType\":\"Linear\",\"enumContent\":1}}}}",
|
||||||
|
btree!(TestState::new(0.0)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_run() {
|
||||||
|
let mut bracket = bracket::Bracket::<TestState>::initialize("./temp".to_string())
|
||||||
|
.expect("Bracket failed to initialize");
|
||||||
|
|
||||||
|
bracket.mutate(|b| drop(b.iteration_scaling(bracket::IterationScaling::Linear(2))))
|
||||||
|
.expect("Failed to set iteration scaling");
|
||||||
|
|
||||||
|
for _ in 0..3 {
|
||||||
|
bracket.mutate(|b| drop(b.run_simulation_step()))
|
||||||
|
.expect("Failed to run step");
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
format!("{}", bracket),
|
||||||
|
format!("{{\"tree\":{},\"step\":3,\"iteration_scaling\":{{\"enumType\":\"Linear\",\"enumContent\":2}}}}",
|
||||||
|
btree!(
|
||||||
|
TestState::new(6.0),
|
||||||
|
Some(btree!(
|
||||||
|
TestState::new(6.0),
|
||||||
|
Some(btree!(TestState::new(4.0),
|
||||||
|
Some(btree!(TestState::new(2.0))),
|
||||||
|
Some(btree!(TestState::new(2.0))))),
|
||||||
|
Some(btree!(TestState::new(4.0)))
|
||||||
|
)),
|
||||||
|
Some(btree!(TestState::new(6.0)))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,21 +1,20 @@
|
||||||
use super::super::file_linked::FileLinked;
|
use super::super::file_linked::FileLinked;
|
||||||
use super::super::tree::Tree;
|
|
||||||
|
|
||||||
#[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, Some(btree!(2)), Some(btree!(3, Some(btree!(4)),)));
|
||||||
let mut linked_tree = FileLinked::new(tree, "blah.txt")?;
|
let mut linked_tree = FileLinked::new(tree, String::from("blah.txt"))?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{}", linked_tree.readonly()),
|
format!("{}", linked_tree.readonly()),
|
||||||
"val = 1\n\n[left]\nval = 2\n\n[right]\nval = 3\n\n[right.left]\nval = 4\n"
|
"{\"val\":1,\"left\":{\"val\":2,\"left\":null,\"right\":null},\"right\":{\"val\":3,\"left\":{\"val\":4,\"left\":null,\"right\":null},\"right\":null}}"
|
||||||
);
|
);
|
||||||
|
|
||||||
linked_tree.mutate(|v1| v1.val = 10)?;
|
linked_tree.mutate(|v1| v1.val = 10)?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{}", linked_tree.readonly()),
|
format!("{}", linked_tree.readonly()),
|
||||||
"val = 10\n\n[left]\nval = 2\n\n[right]\nval = 3\n\n[right.left]\nval = 4\n"
|
"{\"val\":10,\"left\":{\"val\":2,\"left\":null,\"right\":null},\"right\":{\"val\":3,\"left\":{\"val\":4,\"left\":null,\"right\":null},\"right\":null}}"
|
||||||
);
|
);
|
||||||
|
|
||||||
linked_tree.mutate(|v1| {
|
linked_tree.mutate(|v1| {
|
||||||
|
@ -26,7 +25,7 @@ fn test_mutate() -> Result<(), String> {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{}", linked_tree.readonly()),
|
format!("{}", linked_tree.readonly()),
|
||||||
"val = 10\n\n[left]\nval = 13\n\n[right]\nval = 3\n\n[right.left]\nval = 4\n"
|
"{\"val\":10,\"left\":{\"val\":13,\"left\":null,\"right\":null},\"right\":{\"val\":3,\"left\":{\"val\":4,\"left\":null,\"right\":null},\"right\":null}}"
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -20,7 +20,7 @@ fn test_new() {
|
||||||
fn test_fmt() {
|
fn test_fmt() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{}", btree!("foo", Some(btree!("bar")),),),
|
format!("{}", btree!("foo", Some(btree!("bar")),),),
|
||||||
"val = \"foo\"\n\n[left]\nval = \"bar\"\n"
|
"{\"val\":\"foo\",\"left\":{\"val\":\"bar\",\"left\":null,\"right\":null},\"right\":null}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ fn test_fmt_node() {
|
||||||
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"))))),
|
||||||
"val = \"foo\"\n"
|
"{\"val\":\"foo\",\"left\":null,\"right\":null}"
|
||||||
);
|
);
|
||||||
assert_eq!(Tree::<i32>::fmt_node(&None), "_");
|
assert_eq!(Tree::<i32>::fmt_node(&None), "_");
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ macro_rules! btree {
|
||||||
$crate::tree::Tree::new($val, $l.and_then(|l| Some(Box::new(l))), None)
|
$crate::tree::Tree::new($val, $l.and_then(|l| Some(Box::new(l))), None)
|
||||||
};
|
};
|
||||||
($val:expr) => {
|
($val:expr) => {
|
||||||
Tree::new($val, None, None)
|
$crate::tree::Tree::new($val, None, None)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ impl<T> Tree<T> {
|
||||||
|
|
||||||
impl<T: fmt::Display + Serialize> fmt::Display for Tree<T> {
|
impl<T: fmt::Display + Serialize> fmt::Display for Tree<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let result = toml::to_string(self);
|
let result = serde_json::to_string(self);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(string) => write!(f, "{}", string),
|
Ok(string) => write!(f, "{}", string),
|
||||||
|
@ -127,6 +127,6 @@ where
|
||||||
type Err = String;
|
type Err = String;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
toml::from_str(s).map_err(|_| format!("Unable to parse string {}", s))
|
serde_json::from_str(s).map_err(|_| format!("Unable to parse string {}", s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue