Ejemplo n.º 1
0
        private static ITreeProgram <TOutput> GetLargestCommon(
            ref ITreeProgram <TOutput> prog1, ref ITreeProgram <TOutput> prog2,
            ISet <ITreeProgram <TOutput> > ignorePrograms = null)
        {
            // gets sub-programs and sort descendingly
            var subProgs1 = new SortedSet <ITreeProgram <TOutput> >(prog1.GetSubPrograms(),
                                                                    Comparer <ITreeProgram <TOutput> > .Create((a, b) => - (a.Length == b.Length
                                                           ? a.CompareTo(b)
                                                           : a.Length.CompareTo(b.Length))));
            var subProgs2 = new HashSet <ITreeProgram <TOutput> >(prog2.GetSubPrograms());

            return(subProgs1.FirstOrDefault(
                       subProg1 =>
                       (ignorePrograms == null || !ignorePrograms.Contains(subProg1)) && subProgs2.Contains(subProg1)));
        }
Ejemplo n.º 2
0
        private static IDictionary <ITreeProgram <TOutput>, uint> GetSubPrograms(ITreeProgram <TOutput> program)
        {
            // organizes sub-programs in dictionary-count form
            var subProgs       = program.GetSubPrograms();
            var subProgsCounts = new Dictionary <ITreeProgram <TOutput>, uint>();

            foreach (var subProg in subProgs)
            {
                if (!subProgsCounts.ContainsKey(subProg))
                {
                    subProgsCounts.Add(subProg, 0);
                }
                subProgsCounts[subProg]++;
            }
            return(subProgsCounts);
        }
Ejemplo n.º 3
0
        private static double Calculate(ITreeProgram <TOutput> prog1, ITreeProgram <TOutput> prog2)
        {
            // checks simple cases
            if (prog1 == null || prog2 == null)
            {
                return(0);
            }
            if (prog1.Equals(prog2))
            {
                return(1);
            }

            // replace all common sub-programs by weighted variables
            var ignorePrograms = new HashSet <ITreeProgram <TOutput> >();
            var minCount       = Math.Min(prog1.Length, prog2.Length);

            for (var i = 0; i < minCount; i++)
            {
                var largestCommon = GetLargestCommon(ref prog1, ref prog2, ignorePrograms);
                if (largestCommon == null || largestCommon.Length < 2)
                {
                    break;
                }
                var newSubProgram = new WeightedVariable(largestCommon.Expression, largestCommon.Length);
                prog1 = prog1.Replace(largestCommon, newSubProgram);
                prog2 = prog2.Replace(largestCommon, newSubProgram);
                ignorePrograms.Add(newSubProgram);
            }

            // gets sub-programs
            var subProgs1 = new List <ITreeProgram <TOutput> > {
                prog1
            };

            subProgs1.AddRange(prog1.GetSubPrograms());
            var subProgs2 = new List <ITreeProgram <TOutput> > {
                prog2
            };

            subProgs2.AddRange(prog2.GetSubPrograms());

            // tries to align both trees in all possible ways
            var minRelCost = double.MaxValue;

            for (var i = 0u; i < prog1.Length; i++)
            {
                for (var j = 0u; j < prog2.Length; j++)
                {
                    // alignment is determined by the starting indexes of both trees
                    var idx1 = i;
                    var idx2 = j;

                    // adds cost of having to add previous nodes (shifting/alignment cost)
                    var cost      = i + j;
                    var totalCost = cost;

                    // gets edit cost between sub-programs
                    GetEditCost(subProgs1, subProgs2, ref idx1, ref idx2, ref cost, ref totalCost);

                    // checks cost of having to add remaining nodes
                    var remainder = prog1.Length - idx1 + prog2.Length - idx2 - 2;
                    cost      += remainder;
                    totalCost += remainder;
                    var relCost = (double)cost / totalCost;

                    // updates min relative cost
                    if (relCost < minRelCost)
                    {
                        minRelCost = relCost;
                    }
                }
            }

            return(1d - minRelCost);
        }