/// <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); }