コード例 #1
0
        private void SetResult(EvaluationContext context, FunctionFoundEventArgs <Derivatives <Func <double> > > args, IFunction <double, double> doubleFunction)
        {
            var argumentCount = args.ArgumentCount;

            var variableCount = 1;

            for (var i = 0; i < argumentCount; i++)
            {
                variableCount = Math.Max(variableCount, args[i].Count);
            }

            var result = new DoubleDerivatives(variableCount);

            var arguments = new Func <double> [argumentCount];

            for (var i = 0; i < argumentCount; i++)
            {
                var iLocal = i;
                arguments[i] = () => args[iLocal][0]();
            }

            result[0] = () =>
            {
                var argumentValues = arguments.Select(arg => arg()).ToArray();

                return(doubleFunction.Logic(string.Empty, argumentValues, context));
            };

            if (doubleFunction is IDerivativeFunction <double, double> derivativeFunction)
            {
                var derivatives = new Lazy <Derivatives <Func <double> > >(() => derivativeFunction.Derivative(string.Empty, args, context));

                for (var i = 1; i <= variableCount; i++)
                {
                    var derivativeIndex = i;

                    if (IsDerivativeDefined(args, derivativeIndex))
                    {
                        result[i] = () => GetDerivativeValue(args, derivativeIndex, argumentCount, derivatives);
                    }
                }
            }

            args.Result = result;
        }
コード例 #2
0
        /// <summary>
        /// Exponentials
        /// </summary>
        public static Derivatives <Func <double> > ApplyExp(Derivatives <Func <double> >[] arguments)
        {
            arguments.ThrowIfNot(nameof(arguments), 1);
            var arg    = arguments[0];
            var result = new DoubleDerivatives(arg.Count);
            var a0     = arg[0];

            result[0] = () => Math.Exp(a0());

            // Chain rule for derivatives
            for (var i = 1; i < arg.Count; i++)
            {
                if (arg[i] != null)
                {
                    var ai = arg[i];
                    result[i] = () => Math.Exp(a0()) * ai();
                }
            }
            return(result);
        }
コード例 #3
0
        /// <summary>
        /// Applies the square root.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns>The square root result.</returns>
        public static Derivatives <Func <double> > ApplySqrt(Derivatives <Func <double> >[] arguments)
        {
            arguments.ThrowIfNot(nameof(arguments), 1);
            var a      = arguments[0];
            var result = new DoubleDerivatives(a.Count);
            var a0     = a[0];

            result[0] = () => Math.Sqrt(a0());

            // Apply the chain rule
            for (var i = 1; i < a.Count; i++)
            {
                if (a[i] != null)
                {
                    var ai = a[i];
                    result[i] = () => - 0.5 * ai() / Math.Sqrt(a0());
                }
            }
            return(result);
        }
コード例 #4
0
        /// <summary>
        /// Applies the absolute value.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns>The absolute value result.</returns>
        public static Derivatives <Func <double> > ApplyAbs(Derivatives <Func <double> >[] arguments)
        {
            arguments.ThrowIfNot(nameof(arguments), 1);
            var arg    = arguments[0];
            var result = new DoubleDerivatives(arg.Count);
            var a0     = arg[0];

            result[0] = () => Math.Abs(a0());

            // Apply chain rule
            for (var i = 1; i < arg.Count; i++)
            {
                if (arg[i] != null)
                {
                    var ai = arg[i];
                    result[i] = () =>
                    {
                        var tmp = a0();
                        return(tmp > 0 ? ai() : tmp < 0 ? -ai() : 0);
                    };
                }
            }
            return(result);
        }
コード例 #5
0
        /// <summary>
        /// Applies the arctangent.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns>The arctangent result.</returns>
        public static Derivatives <Func <double> > ApplyAtan(Derivatives <Func <double> >[] arguments)
        {
            arguments.ThrowIfNot(nameof(arguments), 1);
            var arg    = arguments[0];
            var result = new DoubleDerivatives(arg.Count);
            var a0     = arg[0];

            result[0] = () => Math.Atan(a0());

            // Apply the chain rule
            for (var i = 1; i < arg.Count; i++)
            {
                if (arg[i] != null)
                {
                    var ai = arg[i];
                    result[i] = () =>
                    {
                        var x = a0();
                        return(ai() / (1 + x * x));
                    };
                }
            }
            return(result);
        }
コード例 #6
0
        /// <summary>
        /// Logarithms
        /// </summary>
        public static Derivatives <Func <double> > ApplyLog(Derivatives <Func <double> >[] arguments)
        {
            arguments.ThrowIfEmpty(nameof(arguments));
            if (arguments.Length == 1)
            {
                // Ln(f(x))' = 1/f(x)*f'(x)
                var arg    = arguments[0];
                var result = new DoubleDerivatives(arg.Count);
                var a0     = arg[0];
                result[0] = () => Math.Log(a0());

                // Chain rule
                for (var i = 1; i < arg.Count; i++)
                {
                    if (arg[i] != null)
                    {
                        var ai = arg[i];
                        result[i] = () => ai() / a0();
                    }
                }
                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 DoubleDerivatives(size);
                var g0     = g[0];
                var f0     = f[0];
                result[0] = () => Math.Log(g0(), f0());

                // Chain rule
                for (var i = 1; i < size; i++)
                {
                    if (g[i] != null && f[i] != null)
                    {
                        var gi = g[i];
                        var fi = f[i];
                        result[i] = () =>
                        {
                            var tmpf0 = f0();
                            var tmpg0 = g0();
                            return(gi() / tmpg0 / Math.Log(tmpf0) - fi() / tmpf0 * Math.Log(tmpg0, tmpf0));
                        };
                    }
                    else if (g[i] != null)
                    {
                        var gi = g[i];
                        result[i] = () => gi() / g0() / Math.Log(f0());
                    }
                    else if (f[i] != null)
                    {
                        var fi = f[i];
                        result[i] = () =>
                        {
                            var tmpf0 = f0();
                            return(-fi() / f0() * Math.Log(g0(), tmpf0));
                        };
                    }
                }
                return(result);
            }

            throw new CircuitException("Invalid number of arguments, {0} given but 2 expected".FormatString(arguments.Length));
        }
コード例 #7
0
        /// <summary>
        /// Applies the maximum operator.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns>The maximum result.</returns>
        public static Derivatives <Func <double> > ApplyMax(Derivatives <Func <double> >[] 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 DoubleDerivatives(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] = () => Math.Max(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] = () => funca() > funcb() ? tmpda() : tmpdb(); // Use the derivative of the function that is currently the smallest
                        }
                        else if (tmpda != null)
                        {
                            result[k] = () => funca() > funcb() ? tmpda() : 0;
                        }
                        else if (tmpdb != null)
                        {
                            result[k] = () => funca() > funcb() ? 0 : tmpdb();
                        }
                    }
                }
            }

            for (var i = 2; i < arguments.Length; i++)
            {
                // First two arguments
                var a = result[0];
                var b = arguments[i][0];
                result[0] = () => Math.Max(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] = () => funca() > funcb() ? tmpda() : tmpdb(); // Use the derivative of the function that is currently the smallest
                        }
                        else if (tmpda != null)
                        {
                            result[k] = () => funca() > funcb() ? tmpda() : 0;
                        }
                        else if (tmpdb != null)
                        {
                            result[k] = () => funca() > funcb() ? 0 : tmpdb();
                        }
                    }
                }
            }
            return(result);
        }