mwchase icon

LC:NN upload 7: bye for now

mwchase | PRO | 04/13/17 04:55:49 PM UTC | 0 ⭐ | 963 👁️ | Never ⏰ | []
Diff |

17.39 KB

|

None

|

0 👍

/

0 👎

diff --git a/rust/adagio/Cargo.toml b/rust/adagio/Cargo.toml
--- a/rust/adagio/Cargo.toml
+++ b/rust/adagio/Cargo.toml
@@ -6,3 +6,4 @@
 [dependencies]
 num = "0.1.37"
 num-rational = "0.1.36"
+void = "1.0.2"
diff --git a/rust/adagio/src/builder.rs b/rust/adagio/src/builder.rs
--- a/rust/adagio/src/builder.rs
+++ b/rust/adagio/src/builder.rs
@@ -1,21 +1,21 @@
-use num_rational::Rational;
+use num_rational::Ratio;
 
-use {Environment, Node};
+use {Environment, LiteralType, Node};
 use node_defs::{Container, NodeData, Sum};
+use node_ops::NodeExpr;
 
-impl<T:NodeData> Environment<T> {
-    fn swlu<I: Node<T>>(&mut self, input: Container<I>) -> Container<Sum<T>> where T::Constant: From<Rational> {
-        let leakiness = self.number(Rational::new(1, 10));
-        let one_half = self.number(Rational::new(1, 2));
-        let one = self.number(Rational::new(1, 1));
-        let minus_one = self.number(Rational::new(-1, 1));
-        let tanh = self.tanh(input.clone());
-        let minus_tanh = self.multiply(minus_one, tanh.clone());
-        let one_plus = self.add(one.clone(), tanh);
-        let one_minus = self.add(one, minus_tanh);
-        let scaled = self.multiply(leakiness, one_minus);
-        let sum = self.add(one_plus, scaled);
-        let half_input = self.multiply(one_half, input);
-        self.multiply(half_input, sum)
+impl<T: NodeData> NodeExpr<T> {
+    pub fn swlu(self) -> NodeExpr<T>
+        where T::Constant: From<Ratio<LiteralType>>
+    {
+        self.clone() * constant((1, 2)) *
+        ((self.clone().tanh() + constant(1)) +
+         (constant(1) - self.clone().tanh()) * constant((1, 10)))
     }
-}
\ No newline at end of file
+}
+
+fn constant<T: NodeData, C: Into<Ratio<LiteralType>>>(constant: C) -> NodeExpr<T>
+    where T::Constant: From<Ratio<LiteralType>>
+{
+    NodeExpr::constant(constant.into())
+}
diff --git a/rust/adagio/src/eval.rs b/rust/adagio/src/eval.rs
--- a/rust/adagio/src/eval.rs
+++ b/rust/adagio/src/eval.rs
@@ -66,11 +66,11 @@
 
     fn eval_primitive(&mut self, state: &State, primitive: Container<Primitive<T>>) -> f64 {
         if !self.primitives.contains_key(&primitive.clone()) {
-            let result = match primitive.as_ref() {
-                &Primitive::Input(index) => state.inputs[index],
-                &Primitive::Real(_) => unimplemented!(),
-                &Primitive::Parameter(index) => state.parameters[index],
-                &Primitive::Sigmoid(minus, ref sum) => {
+            let result = match *primitive.as_ref() {
+                Primitive::Input(index) => state.inputs[index],
+                Primitive::Real(_) => unimplemented!(),
+                Primitive::Parameter(index) => state.parameters[index],
+                Primitive::Sigmoid(minus, ref sum) => {
                     let tanh = self.eval_sum(state, sum.clone()).tanh();
                     if minus { -tanh } else { tanh }
                 }
diff --git a/rust/adagio/src/lib.rs b/rust/adagio/src/lib.rs
--- a/rust/adagio/src/lib.rs
+++ b/rust/adagio/src/lib.rs
@@ -1,5 +1,6 @@
 extern crate num;
 extern crate num_rational;
+extern crate void;
 
 use std::cmp::Ordering;
 use std::collections::{HashMap, HashSet};
@@ -9,10 +10,15 @@
 mod eval;
 mod node_conversions;
 mod node_defs;
+mod node_ops;
 mod node_ordering;
 
 use node_conversions::Summable;
 use node_defs::{Container, container, FancyClone, NodeData, Sum, Product, Power, Primitive};
+use node_ops::{AsExpr, NodeExpr};
+
+///Writing code that's generic over scalars is suffering.
+type LiteralType = i32;
 
 /// Negates a Sum node.
 impl<T: NodeData> Sum<T> {
@@ -77,6 +83,19 @@
 }
 
 impl<T: NodeData> Environment<T> {
+    pub fn new() -> Environment<T> {
+        Environment {
+            sum: HashSet::new(),
+            product: HashSet::new(),
+            power: HashSet::new(),
+            primitive: HashSet::new(),
+            sum_derivative: HashMap::new(),
+            product_derivative: HashMap::new(),
+            power_derivative: HashMap::new(),
+            primitive_derivative: HashMap::new(),
+        }
+    }
+
     /// Makes a canonicalized Sum from the given components.
     pub fn make_sum<C, N: Into<T::Constant>>(&mut self,
                                              minus: bool,
@@ -298,9 +317,7 @@
             }
         }
 
-        last = self.add(last, inner);
-        last = self.add(last, outer);
-        self.add(last, first)
+        self.eval(first.expr() + outer.expr() + inner.expr() + last.expr())
     }
 
     fn _combine_terms(&mut self,
@@ -314,9 +331,18 @@
         let mut left_index = 0;
         let mut right_index = 0;
 
-        while left_index < left_length && right_index < right_length {
+        println!("Vectors equal: {}", left == right);
+        //println!("Left: {:?} right: {:?}", left, right);
+
+        while (left_index < left_length) && (right_index < right_length) {
+            assert!(left_index < left.len(), "Left OOB");
+            assert!(right_index < right.len(), "Right OOB");
+            println!("Right len: {} index: {}", right.len(), right_index);
+            let ref right_power = right[right_length];
+            println!("Right indexing succeeded");
+            println!("Left len: {} index: {} right len: {} index: {}", left.len(), left_index, right.len(), right_index);
             let ref left_power = left[left_index];
-            let ref right_power = right[right_length];
+            println!("Left indexing succeeded");
             match left_power.fuzzy_cmp(right_power.as_ref()) {
                 Ordering::Less => {
                     powers.push(left_power.clone());
@@ -351,9 +377,38 @@
         let sum = sum.as_sum(self);
         self.make_sigmoid(false, sum)
     }
+
+    pub fn eval(&mut self, expr: NodeExpr<T>) -> Container<Sum<T>> {
+        match expr {
+            NodeExpr::Sum(a) => a.insert(self),
+            NodeExpr::Product(a) => a.as_sum(self),
+            NodeExpr::Power(a) => a.as_sum(self),
+            NodeExpr::Primitive(a) => a.as_sum(self),
+            NodeExpr::Constant(a) => self.number(a),
+            NodeExpr::Add(a, b) => {
+                let left = self.eval(*a);
+                let right = self.eval(*b);
+                self.add(left, right)
+            }
+            NodeExpr::Subtract(a, b) => {
+                let left = self.eval(*a);
+                let right = self.eval(*b).negate(self);
+                self.add(left, right)
+            }
+            NodeExpr::Multiply(a, b) => {
+                let left = self.eval(*a);
+                let right = self.eval(*b);
+                self.multiply(left, right)
+            }
+            NodeExpr::Tanh(a) => {
+                let sum = self.eval(*a);
+                self.tanh(sum).as_sum(self)
+            }
+        }
+    }
 }
 
-pub trait Node<T: NodeData>: Summable<T> + FancyClone<T> {
+pub trait Node<T: NodeData>: Summable<T> + FancyClone<T> + AsExpr<T> {
     fn partial_derivative(&self,
                           variable: &T::Parameter,
                           env: &mut Environment<T>)
@@ -497,8 +552,8 @@
                        variable: &T::Parameter,
                        env: &mut Environment<T>)
                        -> Container<Sum<T>> {
-        match self {
-            &Primitive::Sigmoid(minus, ref sum) => {
+        match *self {
+            Primitive::Sigmoid(minus, ref sum) => {
                 let derivative = sum.partial_derivative(variable, env);
                 let self_in_env = self.insert(env);
                 let self_squared = env.secret_make_power(self_in_env, 2);
@@ -506,7 +561,7 @@
                 let sum = env.make_sum(minus, 1, vec![minus_self_squared]);
                 env.multiply(derivative, sum)
             }
-            &Primitive::Parameter(ref p) => env.number(if p == variable { 1 } else { 0 }),
+            Primitive::Parameter(ref p) => env.number(if p == variable { 1 } else { 0 }),
             _ => env.number(0),
         }
     }
@@ -527,6 +582,50 @@
 
 #[cfg(test)]
 mod tests {
+    use num_rational;
+    use void;
+
+    use {Environment, LiteralType, NodeData};
+    use node_ops::AsExpr;
     #[test]
-    fn it_works() {}
+    fn construct_xor() {
+        struct MyNodeData(void::Void);
+
+        impl NodeData for MyNodeData {
+            type Constant = num_rational::Ratio<LiteralType>;
+            type Coefficient = num_rational::Ratio<LiteralType>;
+            type Exponent = LiteralType;
+            type Input = usize;
+            type Real = bool; // Pls no use.
+            type Parameter = usize;
+        }
+
+        let mut env = Environment::<MyNodeData>::new();
+        let mut param_count = 0..;
+
+        let left_input = env.make_input(0);
+        let right_input = env.make_input(1);
+
+        let left_hidden =
+            (left_input.expr() * env.make_parameter(param_count.next().unwrap()).expr() +
+             right_input.expr() * env.make_parameter(param_count.next().unwrap()).expr() +
+             env.make_parameter(param_count.next().unwrap()).expr())
+                    .swlu();
+        let right_hidden =
+            (left_input.expr() * env.make_parameter(param_count.next().unwrap()).expr() +
+             right_input.expr() * env.make_parameter(param_count.next().unwrap()).expr() +
+             env.make_parameter(param_count.next().unwrap()).expr())
+                    .swlu();
+
+        let result = left_hidden * env.make_parameter(param_count.next().unwrap()).expr() +
+                     right_hidden * env.make_parameter(param_count.next().unwrap()).expr() +
+                     env.make_parameter(param_count.next().unwrap()).expr();
+
+        let expected = env.make_input(2);
+        let difference = result.clone() - expected.expr();
+        let error = difference.clone() * difference;
+
+        let result_container = env.eval(result);
+        let error_container = env.eval(error);
+    }
 }
diff --git a/rust/adagio/src/node_conversions.rs b/rust/adagio/src/node_conversions.rs
--- a/rust/adagio/src/node_conversions.rs
+++ b/rust/adagio/src/node_conversions.rs
@@ -44,8 +44,8 @@
 
 impl<T: NodeData> Productable<T> for Primitive<T> {
     fn as_product(&self, env: &mut Environment<T>) -> Container<Product<T>> {
-        match self {
-            &Primitive::Sigmoid(true, ref sum) => {
+        match *self {
+            Primitive::Sigmoid(true, ref sum) => {
                 let sigmoid = env.make_sigmoid(false, sum.clone());
                 let power = sigmoid.as_power(env);
                 env.secret_make_product(-1, vec![power])
diff --git a/rust/adagio/src/node_defs.rs b/rust/adagio/src/node_defs.rs
--- a/rust/adagio/src/node_defs.rs
+++ b/rust/adagio/src/node_defs.rs
@@ -5,7 +5,7 @@
 
 use num::{Integer, Signed};
 
-use {Environment, Node};
+use {Environment, LiteralType, Node};
 
 pub type Container<T> = Arc<T>;
 
@@ -14,9 +14,9 @@
 }
 
 pub trait NodeData {
-    type Constant: Hash + Ord + Clone + Signed + Into<Self::Coefficient> + From<i32>;
-    type Coefficient: Hash + Ord + Clone + Signed + Into<Self::Constant> + From<i32>;
-    type Exponent: Hash + Clone + Integer + Into<Self::Constant> + From<i32>;
+    type Constant: Hash + Ord + Clone + Signed + Into<Self::Coefficient> + From<LiteralType>;
+    type Coefficient: Hash + Ord + Clone + Signed + Into<Self::Constant> + From<LiteralType>;
+    type Exponent: Hash + Clone + Integer + Into<Self::Constant> + From<LiteralType>;
     type Input: Hash + Ord + Clone;
     type Real: Hash + Ord + Clone;
     type Parameter: Hash + Ord + Clone;
@@ -130,20 +130,20 @@
 
 impl<T: NodeData> Hash for Primitive<T> {
     fn hash<H: Hasher>(&self, state: &mut H) {
-        match self {
-            &Primitive::Input(ref a) => {
+        match *self {
+            Primitive::Input(ref a) => {
                 "Input".hash(state);
                 a.hash(state)
             }
-            &Primitive::Real(ref a) => {
+            Primitive::Real(ref a) => {
                 "Real".hash(state);
                 a.hash(state)
             }
-            &Primitive::Parameter(ref a) => {
+            Primitive::Parameter(ref a) => {
                 "Parameter".hash(state);
                 a.hash(state)
             }
-            &Primitive::Sigmoid(minus, ref a) => {
+            Primitive::Sigmoid(minus, ref a) => {
                 "Sigmoid".hash(state);
                 minus.hash(state);
                 a.hash(state)
@@ -184,8 +184,8 @@
 
 impl<T: NodeData> FancyClone<T> for Primitive<T> {
     fn fancy_clone(&self, env: &mut Environment<T>) -> Primitive<T> {
-        match self {
-            &Primitive::Sigmoid(minus, ref a) => Primitive::Sigmoid(minus, a.insert(env)),
+        match *self {
+            Primitive::Sigmoid(minus, ref a) => Primitive::Sigmoid(minus, a.insert(env)),
             _ => self.clone(),
         }
     }
@@ -223,11 +223,11 @@
 
 impl<T: NodeData> Clone for Primitive<T> {
     fn clone(&self) -> Primitive<T> {
-        match self {
-            &Primitive::Input(ref a) => Primitive::Input(a.clone()),
-            &Primitive::Real(ref a) => Primitive::Real(a.clone()),
-            &Primitive::Parameter(ref a) => Primitive::Parameter(a.clone()),
-            &Primitive::Sigmoid(minus, ref a) => Primitive::Sigmoid(minus, a.clone()),
+        match *self {
+            Primitive::Input(ref a) => Primitive::Input(a.clone()),
+            Primitive::Real(ref a) => Primitive::Real(a.clone()),
+            Primitive::Parameter(ref a) => Primitive::Parameter(a.clone()),
+            Primitive::Sigmoid(minus, ref a) => Primitive::Sigmoid(minus, a.clone()),
         }
     }
 }
diff --git a/rust/adagio/src/node_ops.rs b/rust/adagio/src/node_ops.rs
new file mode 100644
--- /dev/null
+++ b/rust/adagio/src/node_ops.rs
@@ -0,0 +1,94 @@
+use std::ops::{Add, Mul, Sub};
+
+use Node;
+use node_defs::{NodeData, Sum, Product, Power, Primitive};
+
+pub enum NodeExpr<T: NodeData> {
+    Sum(Sum<T>),
+    Product(Product<T>),
+    Power(Power<T>),
+    Primitive(Primitive<T>),
+    Constant(T::Constant),
+    Add(Box<NodeExpr<T>>, Box<NodeExpr<T>>),
+    Subtract(Box<NodeExpr<T>>, Box<NodeExpr<T>>),
+    Multiply(Box<NodeExpr<T>>, Box<NodeExpr<T>>),
+    Tanh(Box<NodeExpr<T>>),
+}
+
+impl<T: NodeData> Clone for NodeExpr<T> {
+    fn clone(&self) -> NodeExpr<T> {
+        match *self {
+            NodeExpr::Sum(ref a) => NodeExpr::Sum(a.clone()),
+            NodeExpr::Product(ref a) => NodeExpr::Product(a.clone()),
+            NodeExpr::Power(ref a) => NodeExpr::Power(a.clone()),
+            NodeExpr::Primitive(ref a) => NodeExpr::Primitive(a.clone()),
+            NodeExpr::Constant(ref a) => NodeExpr::Constant(a.clone()),
+            NodeExpr::Add(ref a, ref b) => NodeExpr::Add(a.clone(), b.clone()),
+            NodeExpr::Subtract(ref a, ref b) => NodeExpr::Subtract(a.clone(), b.clone()),
+            NodeExpr::Multiply(ref a, ref b) => NodeExpr::Multiply(a.clone(), b.clone()),
+            NodeExpr::Tanh(ref a) => NodeExpr::Tanh(a.clone()),
+        }
+    }
+}
+
+impl<T: NodeData> Add for NodeExpr<T> {
+    type Output = NodeExpr<T>;
+
+    fn add(self, rhs: NodeExpr<T>) -> NodeExpr<T> {
+        NodeExpr::Add(Box::new(self), Box::new(rhs))
+    }
+}
+
+impl<T: NodeData> Sub for NodeExpr<T> {
+    type Output = NodeExpr<T>;
+
+    fn sub(self, rhs: NodeExpr<T>) -> NodeExpr<T> {
+        NodeExpr::Subtract(Box::new(self), Box::new(rhs))
+    }
+}
+
+impl<T: NodeData> Mul for NodeExpr<T> {
+    type Output = NodeExpr<T>;
+
+    fn mul(self, rhs: NodeExpr<T>) -> NodeExpr<T> {
+        NodeExpr::Multiply(Box::new(self), Box::new(rhs))
+    }
+}
+
+pub trait AsExpr<T: NodeData> {
+    fn expr(&self) -> NodeExpr<T>;
+}
+
+impl<T: NodeData> AsExpr<T> for Sum<T> {
+    fn expr(&self) -> NodeExpr<T> {
+        NodeExpr::Sum(self.clone())
+    }
+}
+
+impl<T: NodeData> AsExpr<T> for Product<T> {
+    fn expr(&self) -> NodeExpr<T> {
+        NodeExpr::Product(self.clone())
+    }
+}
+
+impl<T: NodeData> AsExpr<T> for Power<T> {
+    fn expr(&self) -> NodeExpr<T> {
+        NodeExpr::Power(self.clone())
+    }
+}
+
+impl<T: NodeData> AsExpr<T> for Primitive<T> {
+    fn expr(&self) -> NodeExpr<T> {
+        NodeExpr::Primitive(self.clone())
+    }
+}
+
+impl<T: NodeData> NodeExpr<T> {
+    pub fn tanh(self) -> NodeExpr<T> {
+        NodeExpr::Tanh(Box::new(self))
+    }
+
+    pub fn constant<C: Into<T::Constant>>(constant: C) -> NodeExpr<T> {
+        NodeExpr::Constant(constant.into())
+    }
+}
diff --git a/rust/adagio/src/node_ordering.rs b/rust/adagio/src/node_ordering.rs
--- a/rust/adagio/src/node_ordering.rs
+++ b/rust/adagio/src/node_ordering.rs
@@ -12,11 +12,11 @@
 
 impl<T: NodeData> Primitive<T> {
     fn simplify(&self) -> PrimitiveType {
-        match self {
-            &Primitive::Input(_) => PrimitiveType::Input,
-            &Primitive::Real(_) => PrimitiveType::Real,
-            &Primitive::Parameter(_) => PrimitiveType::Parameter,
-            &Primitive::Sigmoid(_, _) => PrimitiveType::Sigmoid,
+        match *self {
+            Primitive::Input(_) => PrimitiveType::Input,
+            Primitive::Real(_) => PrimitiveType::Real,
+            Primitive::Parameter(_) => PrimitiveType::Parameter,
+            Primitive::Sigmoid(_, _) => PrimitiveType::Sigmoid,
         }
     }
 }

Comments