Ejemplo n.º 1
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);
        }