Ejemplo n.º 1
0
        /// <summary>
        ///     Gets the root-mean-square deviation (RMSD) between the values computed for the given programs. The method works by
        ///     substituting the variables in both programs' expressions by random values for a certain number of trials. In each
        ///     trial, the square of the difference between the values computed by both programs is calculated.
        /// </summary>
        /// <param name="program">The first program that we want to test.</param>
        /// <param name="other">The second program that we want to test.</param>
        /// <param name="numTrials">The number of trials used to compute the squared difference.</param>
        /// <returns>The RMSD between the several values computed for the given programs.</returns>
        public static double GetValueRmsd(
            this ITreeProgram <double> program, ITreeProgram <double> other, uint numTrials = DEFAULT_NUM_TRIALS)
        {
            // checks null
            if (program == null || other == null)
            {
                return(double.MaxValue);
            }

            // checks expression or constant equivalence after simplification
            program = program.Simplify();
            other   = other.Simplify();
            if (program.Equals(other) || program.IsConstant() && other.IsConstant())
            {
                return(Math.Abs(program.Compute() - other.Compute()));
            }

            // replaces variables of each expression by custom variables
            var customVariables = new Dictionary <Variable, Variable>();

            program = ReplaceVariables(program, customVariables);
            other   = ReplaceVariables(other, customVariables);
            if (customVariables.Count == 0)
            {
                return(double.MaxValue);
            }

            // gets random values for each variable
            var customVariablesValues = customVariables.Values.ToDictionary(
                variable => variable,
                variable => GetTrialRandomNumbers(numTrials, variable.Range));

            // runs a batch of trials
            var squareDiffSum = 0d;

            for (var i = 0; i < numTrials; i++)
            {
                // replaces the value of each variable by a random number
                foreach (var customVariablesValue in customVariablesValues)
                {
                    customVariablesValue.Key.Value = customVariablesValue.Value[i];
                }

                // computes difference of the resulting values of the expressions
                var prog1Value = program.Compute();
                var prog2Value = other.Compute();
                var diff       = prog1Value.Equals(prog2Value) ? 0 : prog1Value - prog2Value;
                squareDiffSum += diff * diff;
            }

            // returns RMSD
            return(Math.Sqrt(squareDiffSum / numTrials));
        }
Ejemplo n.º 2
0
        /// <summary>
        ///     Checks whether the given <see cref="MathProgram" /> computes a value that is consistently equivalent to that
        ///     computed
        ///     by another program according to some margin. The method works by substituting the variables in both programs'
        ///     expressions by random values for a certain number of trials. In each trial, the difference between the values
        ///     computed by both programs is calculated. If the difference is less than a given margin for all the trials, then the
        ///     programs are considered to be value-equivalent.
        /// </summary>
        /// <param name="program">The first program that we want to test.</param>
        /// <param name="other">The second program that we want to test.</param>
        /// <param name="margin">
        ///     The margin used to compare against the difference of values computed by both expressions in each
        ///     trial.
        /// </param>
        /// <param name="numTrials">The number of trials used to discern whether the given programs are equivalent.</param>
        /// <returns><c>True</c> if the given programs are considered to be value-equivalent, <c>False</c> otherwise.</returns>
        public static bool IsValueEquivalent(
            this ITreeProgram <double> program, ITreeProgram <double> other, double margin = DEFAULT_MARGIN,
            uint numTrials = DEFAULT_NUM_TRIALS)
        {
            // checks null
            if (program == null || other == null)
            {
                return(false);
            }

            // checks equivalence
            if (program.Equals(other))
            {
                return(true);
            }

            // checks expression or constant equivalence after simplification
            program = program.Simplify();
            other   = other.Simplify();
            if (program.Equals(other) ||
                program.IsConstant() && other.IsConstant() && Math.Abs(program.Compute() - other.Compute()) < margin)
            {
                return(true);
            }

            // gets RMSE by replacing the values of the variables in some number of trials
            return(program.GetValueRmsd(other, numTrials) <= margin);
        }
Ejemplo n.º 3
0
        /// <summary>
        ///     Computes a <see cref="Range" /> representing the minimum and maximum values that a given <see cref="MathProgram" />
        ///     can compute, as dictated by its sub-programs.
        /// </summary>
        /// <param name="program">The program whose range we want to compute.</param>
        /// <returns>The range of the given program.</returns>
        public static Range GetRange(this ITreeProgram <double> program)
        {
            // checks for constant value
            if (program.IsConstant())
            {
                var value = program.Compute();
                return(new Range(value, value));
            }

            // checks for variable
            if (program is Variable)
            {
                return(((Variable)program).Range);
            }

            // collects info on ranges of all children
            var childrenRanges = new List <IEnumerable <double> >();

            foreach (var child in program.Input)
            {
                var childRange = GetRange(child);
                childrenRanges.Add(new[] { childRange.Min, childRange.Max });
            }

            // gets all combinations between children ranges
            var min = double.MaxValue;
            var max = double.MinValue;
            var allRangeCombinations = childrenRanges.GetAllCombinations();

            foreach (var rangeCombination in allRangeCombinations)
            {
                // builds new program by replacing children with constant values (range min or max)
                var children = new ITreeProgram <double> [rangeCombination.Count];
                for (var i = 0; i < rangeCombination.Count; i++)
                {
                    children[i] = new Constant(rangeCombination[i]);
                }
                var newElem = program.CreateNew(children);

                // checks min and max values from new prog value
                var val = newElem.Compute();
                min = Math.Min(min, val);
                max = Math.Max(max, val);
            }

            return(new Range(min, max));
        }
Ejemplo n.º 4
0
 /// <summary>
 ///     Verifies whether the <see cref="MathProgram" /> is a constant value, i.e., whether all its descendant leaf
 ///     programs are instances of <see cref="Constant" />, and whether the associated value equals to
 ///     <paramref name="val" />.
 /// </summary>
 /// <returns>
 ///     <c>true</c>, if program is a constant and its value equals <paramref name="val" />, <c>false</c>
 ///     otherwise.
 /// </returns>
 /// <param name="program">The program to verify whether it is a constant.</param>
 /// <param name="val">The value to test for the program.</param>
 public static bool EqualsConstant(this ITreeProgram <double> program, double val) =>
 program.IsConstant() && program.Compute().Equals(val);