use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::cmp::Ordering;
use std::sync::Arc;
use num::{Integer, Signed};
pub type Container<T> = Arc<T>;
pub fn container<T>(data: T) -> Container<T> {
Arc::new(data)
}
pub trait NodeData {
type Constant: Hash + Ord + Clone + Signed;
type Exponent: Hash + Clone + Integer;
type Input: Hash + Ord + Clone;
type SystemVariable: Hash + Ord + Clone;
type Parameter: Hash + Ord + Clone;
}
pub struct Sum<T: NodeData> {
pub pre_hash: u64, //I would like these fields to be private if possible.
pub minus: bool,
pub constant: T::Constant,
pub terms: Vec<Container<Product<T>>>,
}
pub struct Product<T: NodeData> {
pub pre_hash: u64, //I would like these fields to be private if possible.
pub coefficient: T::Constant,
pub powers: Vec<Container<Power<T>>>,
}
pub struct Power<T: NodeData> {
pub exponent: T::Exponent,
pub primitive: Container<Primitive<T>>,
}
pub enum Primitive<T: NodeData> {
Input(T::Input),
SystemVariable(T::SystemVariable),
Parameter(T::Parameter),
Sigmoid(bool, Container<Sum<T>>),
}
impl<T: NodeData> PartialOrd for Sum<T> {
fn partial_cmp(&self, other: &Sum<T>) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T: NodeData> PartialOrd for Product<T> {
fn partial_cmp(&self, other: &Product<T>) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T: NodeData> PartialOrd for Power<T> {
fn partial_cmp(&self, other: &Power<T>) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T: NodeData> PartialOrd for Primitive<T> {
fn partial_cmp(&self, other: &Primitive<T>) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T: NodeData> PartialEq for Sum<T> {
fn eq(&self, other: &Sum<T>) -> bool {
self.minus == other.minus && self.constant == other.constant && self.terms == other.terms
}
}
impl<T: NodeData> PartialEq for Product<T> {
fn eq(&self, other: &Product<T>) -> bool {
self.coefficient == other.coefficient && self.powers == other.powers
}
}
impl<T: NodeData> PartialEq for Power<T> {
fn eq(&self, other: &Power<T>) -> bool {
self.exponent == other.exponent && self.primitive == other.primitive
}
}
impl<T: NodeData> PartialEq for Primitive<T> {
fn eq(&self, other: &Primitive<T>) -> bool {
match (self, other) {
(&Primitive::Input(ref a), &Primitive::Input(ref b)) => a == b,
(&Primitive::SystemVariable(ref a), &Primitive::SystemVariable(ref b)) => a == b,
(&Primitive::Parameter(ref a), &Primitive::Parameter(ref b)) => a == b,
(&Primitive::Sigmoid(minus_a, ref a), &Primitive::Sigmoid(minus_b, ref b)) => {
minus_a == minus_b && a == b
}
_ => false,
}
}
}
impl<T: NodeData> Eq for Sum<T> {}
impl<T: NodeData> Eq for Product<T> {}
impl<T: NodeData> Eq for Power<T> {}
impl<T: NodeData> Eq for Primitive<T> {}
impl<T: NodeData> Hash for Sum<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.pre_hash.hash(state);
}
}
impl<T: NodeData> Hash for Product<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.pre_hash.hash(state);
}
}
impl<T: NodeData> Hash for Power<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.exponent.hash(state);
self.primitive.hash(state);
}
}
impl<T: NodeData> Hash for Primitive<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
&Primitive::Input(ref a) => {
"Input".hash(state);
a.hash(state)
}
&Primitive::SystemVariable(ref a) => {
"SystemVariable".hash(state);
a.hash(state)
}
&Primitive::Parameter(ref a) => {
"Parameter".hash(state);
a.hash(state)
}
&Primitive::Sigmoid(minus, ref a) => {
"Sigmoid".hash(state);
minus.hash(state);
a.hash(state)
}
}
}
}
impl<T: NodeData> Clone for Sum<T> {
fn clone(&self) -> Sum<T> {
Sum {
pre_hash: self.pre_hash.clone(),
minus: self.minus.clone(),
constant: self.constant.clone(),
terms: self.terms.clone(),
}
}
}
impl<T: NodeData> Clone for Product<T> {
fn clone(&self) -> Product<T> {
Product {
pre_hash: self.pre_hash.clone(),
coefficient: self.coefficient.clone(),
powers: self.powers.clone(),
}
}
}
impl<T: NodeData> Clone for Power<T> {
fn clone(&self) -> Power<T> {
Power {
exponent: self.exponent.clone(),
primitive: self.primitive.clone(),
}
}
}
impl<T: NodeData> Clone for Primitive<T> {
fn clone(&self) -> Primitive<T> {
match self {
&Primitive::Input(ref a) => Primitive::Input(a.clone()),
&Primitive::SystemVariable(ref a) => Primitive::SystemVariable(a.clone()),
&Primitive::Parameter(ref a) => Primitive::Parameter(a.clone()),
&Primitive::Sigmoid(minus, ref a) => Primitive::Sigmoid(minus, a.clone()),
}
}
}
impl<T: NodeData> Sum<T> {
pub fn new(minus: bool, constant: T::Constant, terms: Vec<Container<Product<T>>>) -> Sum<T> {
let mut s = DefaultHasher::new();
minus.hash(&mut s);
constant.hash(&mut s);
terms.hash(&mut s);
Sum {
pre_hash: s.finish(),
minus: minus,
constant: constant,
terms: terms,
}
}
}
impl<T: NodeData> Product<T> {
pub fn new(coefficient: T::Constant, powers: Vec<Container<Power<T>>>) -> Product<T> {
let mut s = DefaultHasher::new();
coefficient.hash(&mut s);
powers.hash(&mut s);
Product {
pre_hash: s.finish(),
coefficient: coefficient,
powers: powers,
}
}
}
impl<T: NodeData> Power<T> {
pub fn new(exponent: T::Exponent, primitive: Container<Primitive<T>>) -> Power<T> {
Power {
exponent: exponent,
primitive: primitive,
}
}
}
Comments