Revising binary tree
This commit is contained in:
parent
9662155604
commit
de4a44c93e
3 changed files with 128 additions and 138 deletions
|
@ -297,12 +297,13 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: fmt::Display> fmt::Display for FileLinked<T>
|
impl<T> fmt::Debug for FileLinked<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: fmt::Debug
|
||||||
|
+ Serialize,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", self.val)
|
write!(f, "{:?}", self.val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ use serde::de::DeserializeOwned;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::string::ToString;
|
|
||||||
|
|
||||||
/// As the bracket tree increases in height, `IterationScaling` can be used to configure the number of iterations that
|
/// As the bracket tree increases in height, `IterationScaling` can be used to configure the number of iterations that
|
||||||
/// a node runs for.
|
/// a node runs for.
|
||||||
|
@ -37,12 +36,6 @@ use std::string::ToString;
|
||||||
/// # }
|
/// # }
|
||||||
/// # }
|
/// # }
|
||||||
/// #
|
/// #
|
||||||
/// # impl fmt::Display for TestState {
|
|
||||||
/// # fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
/// # write!(f, "{}", self.score)
|
|
||||||
/// # }
|
|
||||||
/// # }
|
|
||||||
/// #
|
|
||||||
/// # impl TestState {
|
/// # impl TestState {
|
||||||
/// # fn new(score: f64) -> TestState {
|
/// # fn new(score: f64) -> TestState {
|
||||||
/// # TestState { score: score }
|
/// # TestState { score: score }
|
||||||
|
@ -84,7 +77,7 @@ use std::string::ToString;
|
||||||
/// # std::fs::remove_file("./temp").expect("Unable to remove file");
|
/// # std::fs::remove_file("./temp").expect("Unable to remove file");
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, Copy)]
|
#[derive(Clone, Serialize, Deserialize, Copy)]
|
||||||
#[serde(tag = "enumType", content = "enumContent")]
|
#[serde(tag = "enumType", content = "enumContent")]
|
||||||
pub enum IterationScaling {
|
pub enum IterationScaling {
|
||||||
/// Scales the number of simulations linearly with the height of the bracket tree given by `f(x) = mx` where
|
/// Scales the number of simulations linearly with the height of the bracket tree given by `f(x) = mx` where
|
||||||
|
@ -100,7 +93,7 @@ impl Default for IterationScaling {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for IterationScaling {
|
impl fmt::Debug for IterationScaling {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
|
@ -116,7 +109,7 @@ impl fmt::Display for IterationScaling {
|
||||||
/// individuals.
|
/// individuals.
|
||||||
///
|
///
|
||||||
/// [`GeneticNode`]: genetic_node::GeneticNode
|
/// [`GeneticNode`]: genetic_node::GeneticNode
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct Bracket<T>
|
pub struct Bracket<T>
|
||||||
where
|
where
|
||||||
T: genetic_node::GeneticNode,
|
T: genetic_node::GeneticNode,
|
||||||
|
@ -125,9 +118,10 @@ where
|
||||||
iteration_scaling: IterationScaling,
|
iteration_scaling: IterationScaling,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: fmt::Display + Serialize> fmt::Display for Bracket<T>
|
impl<T> fmt::Debug for Bracket<T>
|
||||||
where
|
where
|
||||||
T: genetic_node::GeneticNode,
|
T: genetic_node::GeneticNode
|
||||||
|
+ Serialize
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
|
@ -141,13 +135,11 @@ where
|
||||||
impl<T> Bracket<T>
|
impl<T> Bracket<T>
|
||||||
where
|
where
|
||||||
T: genetic_node::GeneticNode
|
T: genetic_node::GeneticNode
|
||||||
+ ToString
|
+ FromStr
|
||||||
+ FromStr
|
+ Default
|
||||||
+ Default
|
+ DeserializeOwned
|
||||||
+ fmt::Display
|
+ Serialize
|
||||||
+ DeserializeOwned
|
+ Clone,
|
||||||
+ Serialize
|
|
||||||
+ Clone,
|
|
||||||
{
|
{
|
||||||
/// Initializes a bracket of type `T` storing the contents to `file_path`
|
/// Initializes a bracket of type `T` storing the contents to `file_path`
|
||||||
///
|
///
|
||||||
|
@ -160,7 +152,7 @@ where
|
||||||
/// # use std::str::FromStr;
|
/// # use std::str::FromStr;
|
||||||
/// # use std::string::ToString;
|
/// # use std::string::ToString;
|
||||||
/// #
|
/// #
|
||||||
/// #[derive(Default, Deserialize, Serialize, Clone)]
|
/// #[derive(Default, Deserialize, Serialize, Debug, Clone)]
|
||||||
/// struct TestState {
|
/// struct TestState {
|
||||||
/// pub score: f64,
|
/// pub score: f64,
|
||||||
/// }
|
/// }
|
||||||
|
@ -215,9 +207,9 @@ where
|
||||||
/// .expect("Bracket failed to initialize");
|
/// .expect("Bracket failed to initialize");
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// format!("{}", bracket),
|
/// format!("{:?}", bracket),
|
||||||
/// format!("{{\"tree\":{},\"iteration_scaling\":{{\"enumType\":\"Constant\",\"enumContent\":1}}}}",
|
/// format!("{{\"tree\":{:?},\"iteration_scaling\":{{\"enumType\":\"Constant\",\"enumContent\":1}}}}",
|
||||||
/// btree!(TestState::new(0.0)))
|
/// btree!(TestState{score: 0.0}))
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// std::fs::remove_file("./temp").expect("Unable to remove file");
|
/// std::fs::remove_file("./temp").expect("Unable to remove file");
|
||||||
|
@ -441,11 +433,10 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
|
|
||||||
#[derive(Default, Deserialize, Serialize, Clone)]
|
#[derive(Default, Deserialize, Serialize, Clone, Debug)]
|
||||||
struct TestState {
|
struct TestState {
|
||||||
pub score: f64,
|
pub score: f64,
|
||||||
}
|
}
|
||||||
|
@ -458,18 +449,6 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 genetic_node::GeneticNode for TestState {
|
impl genetic_node::GeneticNode for TestState {
|
||||||
fn simulate(&mut self, iterations: u64) -> Result<(), String> {
|
fn simulate(&mut self, iterations: u64) -> Result<(), String> {
|
||||||
self.score += iterations as f64;
|
self.score += iterations as f64;
|
||||||
|
@ -499,9 +478,9 @@ mod tests {
|
||||||
.expect("Bracket failed to initialize");
|
.expect("Bracket failed to initialize");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{}", bracket),
|
format!("{:?}", bracket),
|
||||||
format!("{{\"tree\":{},\"iteration_scaling\":{{\"enumType\":\"Constant\",\"enumContent\":1}}}}",
|
format!("{{\"tree\":{:?},\"iteration_scaling\":{{\"enumType\":\"Constant\",\"enumContent\":1}}}}",
|
||||||
btree!(TestState::new(0.0)))
|
btree!(TestState{score: 0.0}))
|
||||||
);
|
);
|
||||||
|
|
||||||
std::fs::remove_file("./temp").expect("Unable to remove file");
|
std::fs::remove_file("./temp").expect("Unable to remove file");
|
||||||
|
@ -522,27 +501,27 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{}", bracket),
|
format!("{:?}", bracket),
|
||||||
format!("{{\"tree\":{},\"iteration_scaling\":{{\"enumType\":\"Linear\",\"enumContent\":2}}}}",
|
format!("{{\"tree\":{:?},\"iteration_scaling\":{{\"enumType\":\"Linear\",\"enumContent\":2}}}}",
|
||||||
btree!(
|
btree!(
|
||||||
TestState::new(12.0),
|
TestState{score: 12.0},
|
||||||
btree!(
|
btree!(
|
||||||
TestState::new(12.0),
|
TestState{score: 12.0},
|
||||||
btree!(TestState::new(6.0),
|
btree!(TestState{score: 6.0},
|
||||||
btree!(TestState::new(2.0)),
|
btree!(TestState{score: 2.0}),
|
||||||
btree!(TestState::new(2.0))),
|
btree!(TestState{score: 2.0})),
|
||||||
btree!(TestState::new(6.0),
|
btree!(TestState{score: 6.0},
|
||||||
btree!(TestState::new(2.0)),
|
btree!(TestState{score: 2.0}),
|
||||||
btree!(TestState::new(2.0)))
|
btree!(TestState{score: 2.0}))
|
||||||
),
|
),
|
||||||
btree!(
|
btree!(
|
||||||
TestState::new(12.0),
|
TestState{score: 12.0},
|
||||||
btree!(TestState::new(6.0),
|
btree!(TestState{score: 6.0},
|
||||||
btree!(TestState::new(2.0)),
|
btree!(TestState{score: 2.0}),
|
||||||
btree!(TestState::new(2.0))),
|
btree!(TestState{score: 2.0})),
|
||||||
btree!(TestState::new(6.0),
|
btree!(TestState{score: 6.0},
|
||||||
btree!(TestState::new(2.0)),
|
btree!(TestState{score: 2.0}),
|
||||||
btree!(TestState::new(2.0))))
|
btree!(TestState{score: 2.0})))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,25 +2,18 @@
|
||||||
//!
|
//!
|
||||||
//! # Examples
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
|
||||||
//! //let mut t = Tree::new(1, None, None);
|
|
||||||
//! //let t2 = Tree::new(2, Some(Box::new(t)), Some(Box::new(Tree::new(3, None, None))));
|
|
||||||
//! //let s = format!("{}", t2);
|
|
||||||
//!
|
|
||||||
//! //assert_eq!(s, "(2: (1: _|_)|(3: _|_))");
|
|
||||||
//! //t.left = Some(Box::new(Tree::new(4, None, None)));
|
|
||||||
//! //assert_eq!(Tree::fmt_node(t.left), 4);
|
|
||||||
//! //assert_eq!(Tree::from_str(s), t2);
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//! use gemla::btree;
|
||||||
//! Additionally the `btree!` macro can be used to conveniently initialize trees:
|
//!
|
||||||
//!
|
//! // Tree with 2 nodes, one root node and one on the left side
|
||||||
//! ```no_run
|
//! let mut t = btree!(1, btree!(2),);
|
||||||
//! //# #[macro_use] extern crate tree;
|
//!
|
||||||
//! //# fn main() {
|
//! assert_eq!(t.height(), 2);
|
||||||
//! //let t1 = btree!(1,btree!(2),btree!(3))
|
//! assert_eq!(t.left.unwrap().val, 2);
|
||||||
//! //assert_eq!(format!("{}", t1), "(1: (2: _|_)|(3: _|_)")
|
//! assert_eq!(t.right, None);
|
||||||
//! //# }
|
//!
|
||||||
|
//! t.right = Some(Box::new(btree!(3)));
|
||||||
|
//! assert_eq!(t.right.unwrap().val, 3);
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
@ -34,52 +27,62 @@ use std::str::FromStr;
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// //let mut t = Tree::new(1, None, None);
|
/// use gemla::btree;
|
||||||
/// //let t2 = Tree::new(2, Some(Box::new(t)), Some(Box::new(Tree::new(3, None, None))));
|
///
|
||||||
/// //let s = format!("{}", t2);
|
/// // Tree with 2 nodes, one root node and one on the left side
|
||||||
///
|
/// let mut t = btree!(1, btree!(2),);
|
||||||
/// //assert_eq!(s, "(2: (1: _|_)|(3: _|_))");
|
///
|
||||||
/// //t.left = Some(Box::new(Tree::new(4, None, None)));
|
/// assert_eq!(t.height(), 2);
|
||||||
/// //assert_eq!(Tree::fmt_node(t.left), 4);
|
/// assert_eq!(t.left.unwrap().val, 2);
|
||||||
/// //assert_eq!(Tree::from_str(s), t2);
|
/// assert_eq!(t.right, None);
|
||||||
|
///
|
||||||
|
/// t.right = Some(Box::new(btree!(3)));
|
||||||
|
/// assert_eq!(t.right.unwrap().val, 3);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
#[derive(Default, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
/// Additionally the `btree!` macro can be used to conveniently initialize trees:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// //let t1 = btree!(1,btree!(2),btree!(3))
|
|
||||||
/// //assert_eq!(format!("{}", t1), "(1: (2: _|_)|(3: _|_)")
|
|
||||||
/// ```
|
|
||||||
#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Debug)]
|
|
||||||
pub struct Tree<T> {
|
pub struct Tree<T> {
|
||||||
pub val: T,
|
pub val: T,
|
||||||
pub left: Option<Box<Tree<T>>>,
|
pub left: Option<Box<Tree<T>>>,
|
||||||
pub right: Option<Box<Tree<T>>>,
|
pub right: Option<Box<Tree<T>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used to construct trees in a cleaner manner. `btree!` takes 3 arguments, the first being the
|
/// Short-hand for constructing Trees. `btree!` takes 3 arguments, the first being the
|
||||||
/// value of the root node, and the other two being child nodes. The last two arguments are
|
/// value of the root node, and the other two being child nodes. The last two arguments are
|
||||||
/// optional.
|
/// optional.
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```
|
||||||
/// //#[macro_use]
|
/// use gemla::tree::*;
|
||||||
/// //extern crate gemla;
|
/// use gemla::btree;
|
||||||
/// //
|
///
|
||||||
/// //use gemla::*;
|
/// # fn main() {
|
||||||
/// //
|
/// // A tree with two child nodes.
|
||||||
/// //fn main() {
|
/// let t = btree!(1, btree!(2), btree!(3));
|
||||||
/// // // A tree with two child nodes.
|
/// assert_eq!(t,
|
||||||
/// // let t = btree!(1, Some(btree!(2)), Some(btree!(3)));
|
/// Tree::new(1,
|
||||||
/// //
|
/// Some(Box::new(Tree::new(2, None, None))),
|
||||||
/// // // A tree with only a left node.
|
/// Some(Box::new(Tree::new(3, None, None)))));
|
||||||
/// // let t_left = btree!(1, Some(btree!(2)),);
|
///
|
||||||
/// //
|
/// // A tree with only a left node.
|
||||||
/// // // A tree with only a right node.
|
/// let t_left = btree!(1, btree!(2),);
|
||||||
/// // let t_right = btree!(1, ,Some(btree!(3)));
|
/// assert_eq!(t_left,
|
||||||
/// //
|
/// Tree::new(1,
|
||||||
/// // // A tree with no children nodes.
|
/// Some(Box::new(Tree::new(2, None, None))),
|
||||||
/// // let t_single = btree!(1);
|
/// None));
|
||||||
/// //}
|
///
|
||||||
|
/// // A tree with only a right node.
|
||||||
|
/// let t_right = btree!(1, , btree!(3));
|
||||||
|
/// assert_eq!(t_right,
|
||||||
|
/// Tree::new(1,
|
||||||
|
/// None,
|
||||||
|
/// Some(Box::new(Tree::new(3, None, None)))));
|
||||||
|
///
|
||||||
|
/// // A tree with no child nodes.
|
||||||
|
/// let t_single = btree!(1);
|
||||||
|
/// assert_eq!(t_single,
|
||||||
|
/// Tree::new(1,
|
||||||
|
/// None,
|
||||||
|
/// None));
|
||||||
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! btree {
|
macro_rules! btree {
|
||||||
|
@ -98,11 +101,39 @@ macro_rules! btree {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Tree<T> {
|
impl<T> Tree<T> {
|
||||||
/// Constructs a new tree object.
|
/// Constructs a new [`Tree`] object
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use gemla::tree::*;
|
||||||
|
///
|
||||||
|
/// let t = Tree::new(1, None, None);
|
||||||
|
/// assert_eq!(t, Tree {
|
||||||
|
/// val: 1,
|
||||||
|
/// left: None,
|
||||||
|
/// right: None
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
pub fn new(val: T, left: Option<Box<Tree<T>>>, right: Option<Box<Tree<T>>>) -> Tree<T> {
|
pub fn new(val: T, left: Option<Box<Tree<T>>>, right: Option<Box<Tree<T>>>) -> Tree<T> {
|
||||||
Tree { val, left, right }
|
Tree { val, left, right }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Obtains the height of the longest branch in a [`Tree`]
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use gemla::tree::*;
|
||||||
|
/// use gemla::btree;
|
||||||
|
///
|
||||||
|
/// let t =
|
||||||
|
/// btree!("a",
|
||||||
|
/// btree!("aa",
|
||||||
|
/// btree!("aaa"),),
|
||||||
|
/// btree!("ab"));
|
||||||
|
/// assert_eq!(t.height(), 3);
|
||||||
|
/// ```
|
||||||
pub fn height(&self) -> u64 {
|
pub fn height(&self) -> u64 {
|
||||||
match (self.left.as_ref(), self.right.as_ref()) {
|
match (self.left.as_ref(), self.right.as_ref()) {
|
||||||
(Some(l), Some(r)) => max(l.height(), r.height()) + 1,
|
(Some(l), Some(r)) => max(l.height(), r.height()) + 1,
|
||||||
|
@ -111,19 +142,9 @@ impl<T> Tree<T> {
|
||||||
_ => 1,
|
_ => 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_node(t: &Option<Box<Tree<T>>>) -> String
|
|
||||||
where
|
|
||||||
T: fmt::Display,
|
|
||||||
{
|
|
||||||
match t {
|
|
||||||
Some(n) => format!("{}", (*n).val),
|
|
||||||
_ => String::from("_"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: fmt::Display + Serialize> fmt::Display for Tree<T> {
|
impl<T: fmt::Debug + Serialize> fmt::Debug for Tree<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let result = serde_json::to_string(self);
|
let result = serde_json::to_string(self);
|
||||||
|
|
||||||
|
@ -168,7 +189,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fmt() {
|
fn test_fmt() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{}", btree!("foo", 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}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -179,15 +200,4 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(3, btree!(1, btree!(2), btree!(2, btree!(3),)).height());
|
assert_eq!(3, btree!(1, btree!(2), btree!(2, btree!(3),)).height());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_fmt_node() {
|
|
||||||
let t = btree!(17, btree!(16), btree!(12));
|
|
||||||
assert_eq!(Tree::fmt_node(&t.left), "16");
|
|
||||||
assert_eq!(
|
|
||||||
Tree::fmt_node(&Some(Box::new(btree!(btree!("foo"))))),
|
|
||||||
"{\"val\":\"foo\",\"left\":null,\"right\":null}"
|
|
||||||
);
|
|
||||||
assert_eq!(Tree::<i32>::fmt_node(&None), "_");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue