Exemple #1
0
 /// <summary>
 ///     Checks whether this program is equal to another.
 /// </summary>
 /// <param name="other">The other program to check for equality.</param>
 /// <returns>
 ///     <c>true</c> if the objects are the same or have the same <see cref="Label" /> and their <see cref="Input" />
 ///     sequence is the same.
 /// </returns>
 public bool Equals(MathProgram other)
 {
     return(!(other is null) &&
            (ReferenceEquals(this, other) ||
             this.GetType() == other.GetType() &&
             this._hashCode == other._hashCode &&
             string.Equals(this.Label, other.Label) &&
             this.Input.SequenceEqual(other.Input)));
 }
        /// <summary>
        ///     Simplifies the expression of the given <see cref="MathProgram" /> by returning a sub-combination whose fitness is
        ///     approximately equal to that of the original program by a margin of <paramref name="margin" />, and whose
        ///     expression is naturally simpler, i.e., has fewer sub-programs.
        /// </summary>
        /// <returns>An program corresponding to a simplification of the given program.</returns>
        /// <param name="program">The program we want to simplify.</param>
        /// <param name="fitnessFunction">The fitness function used to determine equivalence.</param>
        /// <param name="margin">
        ///     The acceptable difference between the fitness of the given program and that of a simplified program for them to be
        ///     considered equivalent.
        /// </param>
        public static ITreeProgram <double> Simplify(
            this MathProgram program, IFitnessFunction <MathProgram> fitnessFunction, double margin = DEFAULT_MARGIN)
        {
            // gets original program's fitness and count
            var simplified = program;
            var fitness    = fitnessFunction.Evaluate(program);
            var length     = program.Length;

            // first replaces all sub-programs by infinity and NaN recursively
            var consts = new HashSet <Constant>
            {
                new Constant(double.NegativeInfinity),
                new Constant(double.NaN),
                new Constant(double.PositiveInfinity)
            };
            bool simplificationFound;

            do
            {
                simplificationFound = false;
                var simpLength = simplified.Length;
                for (var i = 0u; i < simpLength && !simplificationFound; i++)
                {
                    if (consts.Contains(simplified.ProgramAt(i)))
                    {
                        continue;
                    }
                    foreach (var constant in consts)
                    {
                        var prog       = (MathProgram)simplified.Replace(i, constant);
                        var fit        = fitnessFunction.Evaluate(prog);
                        var progLength = prog.Length;
                        if (Math.Abs(fit - fitness) < margin && progLength <= length)
                        {
                            simplified          = prog;
                            length              = progLength;
                            simplificationFound = true;
                            break;
                        }
                    }
                }
            } while (simplificationFound);

            // then gets all sub-combinations of the simplified program
            var alternatives = simplified.GetSubCombinations();

            foreach (MathProgram subComb in alternatives)
            {
                var subFit        = fitnessFunction.Evaluate(subComb);
                var subCombLength = subComb.Length;

                //checks their fitness and count
                if (Math.Abs(subFit - fitness) < margin && subCombLength < length)
                {
                    simplified = subComb;
                    length     = subCombLength;
                }
            }

            return(simplified);
        }