Example #1
0
        /// <summary>
        /// Applies the absolute value.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns>The absolute value result.</returns>
        public static Derivatives <Expression> ApplyAbs(Derivatives <Expression>[] arguments)
        {
            arguments.ThrowIfNot(nameof(arguments), 1);
            var arg    = arguments[0];
            var result = new ExpressionTreeDerivatives(arg.Count);

            result[0] = Expression.Call(AbsMethod, arg[0]);

            // Apply chain rule
            for (var i = 1; i < arg.Count; i++)
            {
                if (!arg[i].Equals(0.0))
                {
                    result[i] = Expression.Multiply(arg[i],
                                                    Expression.Condition(
                                                        Expression.GreaterThan(arg[0], Expression.Constant(0.0)),
                                                        Expression.Constant(1.0),
                                                        Expression.Condition(
                                                            Expression.LessThan(arg[0], Expression.Constant(0.0)),
                                                            Expression.Constant(-1.0),
                                                            Expression.Constant(0.0))));
                }
            }
            return(result);
        }
Example #2
0
        /// <summary>
        /// Raises to a power.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns>The result of the power.</returns>
        public static Derivatives <Expression> ApplyPow(Derivatives <Expression>[] arguments)
        {
            arguments.ThrowIfNot(nameof(arguments), 2);
            var f      = arguments[0];
            var g      = arguments[1];
            var size   = Math.Max(f.Count, g.Count);
            var result = new ExpressionTreeDerivatives(size);

            result[0] = Expression.Call(PowMethod, f[0], g[0]);

            // Apply chain rule
            for (var i = 1; i < size; i++)
            {
                if (f[i] != null)
                {
                    result[i] = Expression.Multiply(Expression.Multiply(g[0], f[i]),
                                                    Expression.Call(PowMethod, f[0], Expression.Subtract(g[0], Expression.Constant(1.0))));
                }

                if (g[i] != null)
                {
                    var term = Expression.Multiply(Expression.Multiply(g[i], result[0]),
                                                   Expression.Call(LogMethod, f[0]));
                    if (result[i] == null)
                    {
                        result[i] = term;
                    }
                    else
                    {
                        result[i] = Expression.Add(result[i], term);
                    }
                }
            }
            return(result);
        }
Example #3
0
        protected void Check(double expected, ExpressionTreeDerivatives parsed)
        {
            // Compile
            var actual = Expression.Lambda <Func <double> >(parsed[0]).Compile();
            var tol    = Math.Max(Math.Abs(expected), Math.Abs(actual())) * RelativeTolerance + AbsoluteTolerance;

            Assert.AreEqual(expected, actual(), tol);
        }
Example #4
0
        /// <summary>
        /// Applies the logarithm.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns>The log result.</returns>
        public static Derivatives <Expression> ApplyLog(Derivatives <Expression>[] arguments)
        {
            arguments.ThrowIfEmpty(nameof(arguments));
            if (arguments.Length == 1)
            {
                // Ln(f(x))' = 1/f(x)*f'(x)
                var arg    = arguments[0];
                var result = new ExpressionTreeDerivatives(arg.Count);
                result[0] = Expression.Call(LogMethod, arg[0]);

                // Chain rule
                for (var i = 1; i < arg.Count; i++)
                {
                    if (arg[i] != null)
                    {
                        result[i] = Expression.Divide(arg[i], arg[0]);
                    }
                }
                return(result);
            }

            if (arguments.Length == 2)
            {
                // Log(g(x), f(x)) = Ln(g(x)) / Ln(f(x))
                var g      = arguments[0];
                var f      = arguments[1];
                var size   = Math.Max(f.Count, g.Count);
                var result = new ExpressionTreeDerivatives(size);
                result[0] = Expression.Call(Log2Method, g[0], f[0]);

                // Chain rule
                for (var i = 1; i < size; i++)
                {
                    if (g[i] != null)
                    {
                        result[i] = Expression.Divide(
                            Expression.Divide(g[i], g[0]),
                            Expression.Call(LogMethod, f[0]));
                    }
                    if (f[i] != null)
                    {
                        var term = Expression.Multiply(
                            Expression.Divide(f[i], f[0]), result[0]);
                        if (result[i] == null)
                        {
                            result[i] = Expression.Negate(term);
                        }
                        else
                        {
                            result[i] = Expression.Subtract(result[i], term);
                        }
                    }
                }
                return(result);
            }

            throw new CircuitException("Invalid number of arguments, {0} given but 2 expected".FormatString(arguments.Length));
        }
Example #5
0
        /// <summary>
        /// Applies the exponent operator.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns></returns>
        public static Derivatives <Expression> ApplyExp(Derivatives <Expression>[] arguments)
        {
            arguments.ThrowIfNot(nameof(arguments), 1);
            var arg    = arguments[0];
            var result = new ExpressionTreeDerivatives(arg.Count);

            result[0] = Expression.Call(ExpMethod, new[] { arg[0] });

            // Chain rule for derivatives
            for (var i = 1; i < arg.Count; i++)
            {
                if (arg[i] != null)
                {
                    result[i] = Expression.Multiply(result[0], arg[i]);
                }
            }
            return(result);
        }
Example #6
0
        /// <summary>
        /// Applies the cosine.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns>The cosine result.</returns>
        private static Derivatives <Expression> ApplyCos(Derivatives <Expression>[] arguments)
        {
            arguments.ThrowIfNot(nameof(arguments), 1);
            var arg    = arguments[0];
            var result = new ExpressionTreeDerivatives(arg.Count);

            result[0] = Expression.Call(CosMethod, arg[0]);

            // Apply the chain rule
            for (var i = 1; i < arg.Count; i++)
            {
                if (arg[i] != null)
                {
                    result[i] = Expression.Negate(Expression.Multiply(Expression.Call(SinMethod, arg[0]), arg[i]));
                }
            }
            return(result);
        }
Example #7
0
        /// <summary>
        /// Applies the arctangent.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns>The arctangent result.</returns>
        public static Derivatives <Expression> ApplyAtan(Derivatives <Expression>[] arguments)
        {
            arguments.ThrowIfNot(nameof(arguments), 1);
            var arg    = arguments[0];
            var result = new ExpressionTreeDerivatives(arg.Count);

            result[0] = Expression.Call(AtanMethod, arg[0]);

            // Apply chain rule
            for (var i = 1; i < arg.Count; i++)
            {
                if (arg[i] != null)
                {
                    result[i] = Expression.Divide(arg[i], Expression.Add(Expression.Constant(1.0),
                                                                         Expression.Call(SquareMethod, arg[0])));
                }
            }
            return(result);
        }
Example #8
0
        /// <summary>
        /// Rounds the derivatives.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns>The rounding result.</returns>
        public static Derivatives <Expression> ApplyRound(Derivatives <Expression>[] arguments)
        {
            arguments.ThrowIfEmpty(nameof(arguments));
            var arg = arguments[0];

            if (arguments.Length == 1)
            {
                var result = new ExpressionTreeDerivatives();
                result[0] = Expression.Call(RoundMethod, arg[0]);

                for (var i = 1; i < arg.Count; i++)
                {
                    if (arg[i] != null)
                    {
                        throw new CircuitException("Cannot differentiate Round()");
                    }
                }
                return(result);
            }
            if (arguments.Length == 2)
            {
                var result = new ExpressionTreeDerivatives();
                result[0] = Expression.Call(Round2Method, arg[0], Expression.Convert(Expression.Call(RoundMethod, arguments[1][0]), typeof(int)));

                for (var i = 1; i < arg.Count; i++)
                {
                    if (arg[i] != null)
                    {
                        throw new CircuitException("Cannot differentiate Round()");
                    }
                }
                for (var i = 1; i < arguments[1].Count; i++)
                {
                    if (arguments[1][i] != null)
                    {
                        throw new CircuitException("Cannot differentiate Round()");
                    }
                }
                return(result);
            }
            throw new CircuitException("Invalid number of arguments for Round()");
        }
Example #9
0
        /// <summary>
        /// Applies the maximum.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns>The maximum result.</returns>
        public static Derivatives <Expression> ApplyMax(Derivatives <Expression>[] arguments)
        {
            arguments.ThrowIfEmpty(nameof(arguments));
            var size = 1;

            for (var i = 0; i < arguments.Length; i++)
            {
                size = Math.Max(size, arguments[i].Count);
            }
            var result = new ExpressionTreeDerivatives(size);

            if (arguments.Length == 1)
            {
                result[0] = arguments[0][0];
                return(result);
            }

            {
                // First two arguments
                var a = arguments[0][0];
                var b = arguments[1][0];
                result[0] = Expression.Call(MaxMethod, a, b);
                for (var k = 1; k < size; k++)
                {
                    if (arguments[0][k] != null || arguments[1][k] != null)
                    {
                        CircuitWarning.Warning(null, "Trying to derive Min() for which the derivative may not exist in some points");
                        var tmpda = arguments[0][k];
                        var tmpdb = arguments[1][k];
                        var funca = arguments[0][0];
                        var funcb = arguments[1][0];
                        if (tmpda != null && tmpdb != null)
                        {
                            result[k] = Expression.Condition(Expression.GreaterThan(funca, funcb), tmpda, tmpdb); // Use the derivative of the function that is currently the smallest
                        }
                        else if (tmpda != null)
                        {
                            result[k] = Expression.Condition(Expression.GreaterThan(funca, funcb), tmpda, Expression.Constant(0.0));
                        }
                        else if (tmpdb != null)
                        {
                            result[k] = Expression.Condition(Expression.GreaterThan(funca, funcb), Expression.Constant(0.0), tmpdb);
                        }
                    }
                }
            }

            for (var i = 2; i < arguments.Length; i++)
            {
                // First two arguments
                var a = result[0];
                var b = arguments[i][0];
                result[0] = Expression.Call(MaxMethod, a, b);
                for (var k = 1; k < size; k++)
                {
                    if (arguments[0][k] != null || arguments[1][k] != null)
                    {
                        CircuitWarning.Warning(null, "Trying to derive Min() for which the derivative may not exist in some points");
                        var tmpda = result[k];
                        var tmpdb = arguments[i][k];
                        var funca = a;
                        var funcb = arguments[i][0];
                        if (tmpda != null && tmpdb != null)
                        {
                            result[k] = Expression.Condition(Expression.GreaterThan(funca, funcb), tmpda, tmpdb); // Use the derivative of the function that is currently the smallest
                        }
                        else if (tmpda != null)
                        {
                            result[k] = Expression.Condition(Expression.GreaterThan(funca, funcb), tmpda, Expression.Constant(0.0));
                        }
                        else if (tmpdb != null)
                        {
                            result[k] = Expression.Condition(Expression.GreaterThan(funca, funcb), Expression.Constant(0.0), tmpdb);
                        }
                    }
                }
            }
            return(result);
        }