Compare commits

..

No commits in common. "6f6ef153427a491cc196f95b68766693f0acd734" and "f58cd7f2f6224c2e81a0c7531cc274968925c305" have entirely different histories.

4 changed files with 44 additions and 143 deletions

View file

@ -5,9 +5,5 @@ mod tree;
mod test; mod test;
fn main() { fn main() {
// safely: trust me!! unimplemented!();
// having fun or funly having?
unsafe {
std::hint::unreachable_unchecked()
}
} }

View file

@ -15,26 +15,23 @@ use nom::{branch::alt, bytes::complete::take_while1, character::char, combinator
use crate::tree::{Alternative, Edge, Tree, Vertex}; use crate::tree::{Alternative, Edge, Tree, Vertex};
fn alternative(input: &str) -> IResult<&str, Tree<String, f64>> {
map(
take_while1::<_, &str, Error<&str>>(AsChar::is_alpha),
|a| Tree::<String, f64> {
root: Vertex::Terminal(Alternative{name: a.to_owned()})
}
).parse(input)
}
fn weighted_edge(input: &str) -> IResult<&str, Edge<String, f64>> { fn weighted_edge(input: &str) -> IResult<&str, Edge<String, f64>> {
let weight = delimited( let weight = delimited(
char::<&str, Error<&str>>('['), char::<&str, Error<&str>>('['),
double, double,
char(']') char(']')
); );
let alternative = map(
take_while1::<_, &str, Error<&str>>(AsChar::is_alpha),
|a| Tree::<String, f64> {
root: Vertex::Terminal(Alternative{name: a.to_owned()})
}
);
map( map(
pair(weight, tree), pair(weight, alt((alternative, subtree))),
|(a, b)| Edge{ |(a, b)| Edge{
weight: a, weight: a,
destination: Box::new(b) destination: b
} }
).parse(input) ).parse(input)
} }
@ -43,12 +40,8 @@ pub fn subtree(input: &str) -> IResult<&str, Tree<String, f64>> {
let inner = map( let inner = map(
pair(weighted_edge, weighted_edge), pair(weighted_edge, weighted_edge),
|(a, b)| Tree{ |(a, b)| Tree{
root: Vertex::NonTerminal(a, b) root: Vertex::NonTerminal(Box::new(a), Box::new(b))
} }
); );
delimited(char('('), inner, char(')')).parse(input) delimited(char('('), inner, char(')')).parse(input)
} }
pub fn tree(input: &str) -> IResult<&str, Tree<String, f64>> {
alt((alternative, subtree)).parse(input)
}

View file

@ -12,13 +12,13 @@ fn simple_symmetric_tree() -> Tree<String, f64> {
}; };
let edge_a = Edge { let edge_a = Edge {
weight: 1.0, weight: 1.0,
destination: Box::new(Tree {root: Vertex::Terminal(a)}) destination: Tree {root: Vertex::Terminal(a)}
}; };
let edge_b = Edge { let edge_b = Edge {
weight: 1.0, weight: 1.0,
destination: Box::new(Tree {root: Vertex::Terminal(b)}) destination: Tree {root: Vertex::Terminal(b)}
}; };
let root = Vertex::NonTerminal(edge_a, edge_b); let root = Vertex::NonTerminal(Box::new(edge_a), Box::new(edge_b));
Tree {root: root} Tree {root: root}
} }
@ -32,13 +32,13 @@ fn simple_asymmetric_tree() -> Tree<String, f64> {
}; };
let edge_a = Edge { let edge_a = Edge {
weight: 3.0, weight: 3.0,
destination: Box::new(Tree {root: Vertex::Terminal(a)}) destination: Tree {root: Vertex::Terminal(a)}
}; };
let edge_b = Edge { let edge_b = Edge {
weight: 1.0, weight: 1.0,
destination: Box::new(Tree {root: Vertex::Terminal(b)}) destination: Tree {root: Vertex::Terminal(b)}
}; };
let root = Vertex::NonTerminal(edge_a, edge_b); let root = Vertex::NonTerminal(Box::new(edge_a), Box::new(edge_b));
Tree {root: root} Tree {root: root}
} }
@ -55,23 +55,23 @@ fn complex_tree() -> Tree<String, f64> {
}; };
let edge_a = Edge { let edge_a = Edge {
weight: 2.5, weight: 2.5,
destination: Box::new(Tree {root: Vertex::Terminal(a)}) destination: Tree {root: Vertex::Terminal(a)}
}; };
let edge_b = Edge { let edge_b = Edge {
weight: 1.0, weight: 1.0,
destination: Box::new(Tree {root: Vertex::Terminal(b)}) destination: Tree {root: Vertex::Terminal(b)}
}; };
let edge_ab = Edge{ let edge_ab = Edge{
weight: 0.5, weight: 0.5,
destination: Box::new(Tree { destination: Tree {
root: Vertex::NonTerminal(edge_a, edge_b) root: Vertex::NonTerminal(Box::new(edge_a), Box::new(edge_b))
}) }
}; };
let edge_c = Edge{ let edge_c = Edge{
weight: 1.0, weight: 1.0,
destination: Box::new(Tree {root: Vertex::Terminal(c)}) destination: Tree {root: Vertex::Terminal(c)}
}; };
let root = Vertex::NonTerminal(edge_ab, edge_c); let root = Vertex::NonTerminal(Box::new(edge_ab), Box::new(edge_c));
Tree {root: root} Tree {root: root}
} }
@ -102,7 +102,7 @@ fn choice_probability_test_3() {
fn parser_test_1() { fn parser_test_1() {
assert_eq!( assert_eq!(
{ {
let (_, b) = parser::tree("([1.0]A[1.0]B)").unwrap(); let (_, b) = parser::subtree("([1.0]A[1.0]B)").unwrap();
b b
}, },
simple_symmetric_tree() simple_symmetric_tree()
@ -113,7 +113,7 @@ fn parser_test_1() {
fn parser_test_2() { fn parser_test_2() {
assert_eq!( assert_eq!(
{ {
let (_, b) = parser::tree("([3.0]A[1.0]B)").unwrap(); let (_, b) = parser::subtree("([3.0]A[1.0]B)").unwrap();
b b
}, },
simple_asymmetric_tree() simple_asymmetric_tree()
@ -124,7 +124,7 @@ fn parser_test_2() {
fn parser_test_3() { fn parser_test_3() {
assert_eq!( assert_eq!(
{ {
let (_, b) = parser::tree("([0.5]([2.5]A[1.0]B)[1.0]C)").unwrap(); let (_, b) = parser::subtree("([0.5]([2.5]A[1.0]B)[1.0]C)").unwrap();
b b
}, },
complex_tree() complex_tree()
@ -133,44 +133,21 @@ fn parser_test_3() {
#[test] #[test]
fn test_symmetry_positive() { fn test_symmetry_positive() {
let (_, a) = parser::tree("([3.0]A[1.0]B)").unwrap(); let (_, a) = parser::subtree("([3.0]A[1.0]B)").unwrap();
let (_, b) = parser::tree("([1.0]B[3.0]A)").unwrap(); let (_, b) = parser::subtree("([1.0]B[3.0]A)").unwrap();
assert_eq!(a, b) assert_eq!(a, b)
} }
#[test] #[test]
fn test_symmetry_negative() { fn test_symmetry_negative() {
let (_, a) = parser::tree("([3.0]A[1.0]B)").unwrap(); let (_, a) = parser::subtree("([3.0]A[1.0]B)").unwrap();
let (_, b) = parser::tree("([1.0]A[3.0]B)").unwrap(); let (_, b) = parser::subtree("([1.0]A[3.0]B)").unwrap();
assert_ne!(a, b) assert_ne!(a, b)
} }
#[test] #[test]
fn test_symmetry_complex() { fn test_symmetry_complex() {
let (_, a) = parser::tree("([1.0]C[0.5]([1.0]B[2.5]A))").unwrap(); let (_, a) = parser::subtree("([1.0]C[0.5]([1.0]B[2.5]A))").unwrap();
let (_, b) = parser::tree("([0.5]([2.5]A[1.0]B)[1.0]C)").unwrap(); let (_, b) = parser::subtree("([0.5]([2.5]A[1.0]B)[1.0]C)").unwrap();
assert_eq!(a, b) assert_eq!(a, b)
} }
#[test]
fn test_menu_simple() {
let (_, a) = parser::tree("([3.0]A[1.0]B)").unwrap();
let (_, b) = parser::tree("A").unwrap();
let Some((a_menu_tree, _)) = a.menu_tree(&["A".to_owned()]) else {
panic!("Failed to get tree from menu_tree output")
};
assert_eq!(a_menu_tree, b)
}
#[test]
fn test_menu_complex() {
let (_, a) = parser::tree("([1.0]C[0.5]([1.0]B[2.5]A))").unwrap();
let (_, b) = parser::tree("([1.0]C[1.5]B)").unwrap();
let Some((a_menu_tree, _)) = a.menu_tree(&[
"B".to_owned(), "C".to_owned()
]) else {
panic!("Failed to get tree from menu_tree output")
};
assert_eq!(a_menu_tree, b)
}

View file

@ -1,24 +1,24 @@
use num_traits::Float; use num_traits::Float;
#[derive(PartialEq, Eq, Clone, Debug)] #[derive(PartialEq, Eq, Debug)]
pub struct Alternative<T: Eq + Clone> { pub struct Alternative<T: Eq> {
pub name: T pub name: T
} }
#[derive(PartialEq, Clone, Debug)] #[derive(PartialEq, Debug)]
pub struct Edge<T: Eq + Clone, U: Float> { pub struct Edge<T: Eq, U: Float> {
pub weight: U, pub weight: U,
pub destination: Box<Tree<T, U>> pub destination: Tree<T, U>
} }
#[derive(Clone, Debug)] #[derive(Debug)]
pub enum Vertex<T: Eq + Clone, U: Float> { pub enum Vertex<T: Eq, U: Float> {
NonTerminal(Edge<T, U>, Edge<T, U>), NonTerminal(Box<Edge<T, U>>, Box<Edge<T, U>>),
Terminal(Alternative<T>), Terminal(Alternative<T>),
} }
// implement symmetry // implement symmetry
impl<T: Eq + Clone, U: Float> PartialEq for Vertex<T, U>{ impl<T: Eq, U: Float> PartialEq for Vertex<T, U>{
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
match self { match self {
Vertex::NonTerminal(a, b) => { Vertex::NonTerminal(a, b) => {
@ -39,16 +39,12 @@ impl<T: Eq + Clone, U: Float> PartialEq for Vertex<T, U>{
} }
} }
#[derive(PartialEq, Clone, Debug)] #[derive(PartialEq, Debug)]
pub struct Tree<T: Eq + Clone, U: Float> { pub struct Tree<T: Eq, U: Float> {
pub root: Vertex<T, U> pub root: Vertex<T, U>
} }
pub enum TreeError { impl<T: Eq, U: Float> Tree<T, U> {
EmptyTree,
}
impl<T: Eq + Clone, U: Float> Tree<T, U> {
fn left_edge_weights(&self) -> U { fn left_edge_weights(&self) -> U {
match &self.root { match &self.root {
Vertex::NonTerminal(a, _) => { Vertex::NonTerminal(a, _) => {
@ -95,66 +91,5 @@ impl<T: Eq + Clone, U: Float> Tree<T, U> {
} }
} }
} }
pub fn menu_tree(&self, alternatives: &[T]) -> Option<(Tree<T, U>, U)> {
match &self.root {
Vertex::Terminal(alt) => {
if alternatives.contains(&alt.name) {
Some((self.clone(), U::zero()))
} else {
None
}
},
Vertex::NonTerminal(a, b) => {
let a_menu = a.destination.menu_tree(alternatives);
let b_menu = b.destination.menu_tree(alternatives);
match (a_menu, b_menu) {
(Some((a_tree, a_weight)), Some((b_tree, b_weight))) => {
Some(
(Tree {
root: Vertex::NonTerminal(
Edge {
weight: a.weight + a_weight,
destination: Box::new(a_tree)
},
Edge {
weight: b.weight + b_weight,
destination: Box::new(b_tree)
}
)
}, U::zero())
)
},
(Some((a_tree, a_weight)), None) => {
Some(
(a_tree, a.weight + a_weight)
)
},
(None, Some((b_tree, b_weight))) => {
Some(
(b_tree, b.weight + b_weight)
)
},
(None, None) => None
}
},
}
}
} }
pub struct SimilarityRelation<T: Eq + Clone> {
left: T,
right: T,
with_respect_to: T
}
// implement symmetry
impl<T: Eq + Clone> PartialEq for SimilarityRelation<T> {
fn eq(&self, other: &Self) -> bool {
(
(self.left == other.left && self.right == other.right)
|| (self.left == other.right && self.right == other.left)
)
&& self.with_respect_to == other.with_respect_to
}
}