Example #1
0
        private static void GetEditCost(
            IList <ITreeProgram <TOutput> > subProgs1, IList <ITreeProgram <TOutput> > subProgs2,
            ref uint idx1, ref uint idx2, ref uint curCost, ref uint totalCost)
        {
            totalCost++;
            var subProg1 = idx1 < subProgs1.Count ? subProgs1[(int)idx1] : null;
            var subProg2 = idx2 < subProgs2.Count ? subProgs2[(int)idx2] : null;

            // if programs are equal
            if (subProg1 != null && subProg2 != null && subProg1.Equals(subProg2))
            {
                // just advance both indexes and adds total cost (cur cost remains the same)
                var remainder = subProg1.Length - 1u;
                idx1      += remainder;
                idx2      += remainder;
                totalCost += (subProg1 is WeightedVariable variable ? variable.Weight : subProg1.Length) - 1;
                return;
            }

            // check if one of the sub-programs is null or has no children
            if (subProg1 == null || subProg2 == null ||
                subProg1.Input == null || subProg1.Input.Count == 0 ||
                subProg2.Input == null || subProg2.Input.Count == 0)
            {
                // adds cost of adding / removing the null node
                curCost++;

                // advance the indexes of both sub-trees and adds cost of adding / removing remainder nodes
                if (subProg1 != null)
                {
                    if (subProg1 is WeightedVariable variable)
                    {
                        // it was a swap: ignores cost of adding/removing nodes the original program's nodes
                        totalCost += variable.Weight - 1;
                    }
                    else if (subProg1.Length > 1)
                    {
                        // normal, uncommon program, count cost of adding/removing its nodes
                        var remainder1 = subProg1.Length - 1u;
                        idx1      += remainder1;
                        curCost   += remainder1;
                        totalCost += remainder1;
                    }
                }

                if (subProg2 != null)
                {
                    if (subProg2 is WeightedVariable variable)
                    {
                        // it was a swap: ignores cost of adding/removing nodes the original program's nodes
                        totalCost += variable.Weight - 1;
                    }
                    else if (subProg2.Length > 1)
                    {
                        // normal, uncommon program, count cost of adding/removing its nodes
                        var remainder2 = subProg2.Length - 1u;
                        idx2      += remainder2;
                        curCost   += remainder2;
                        totalCost += remainder2;
                    }
                }

                return;
            }

            // both programs have children, compares type of function
            var sameNode = subProg1.IsLeaf()
                ? subProg2.IsLeaf() && subProg1.Equals(subProg2)
                : subProg1.GetType() == subProg2.GetType();

            // adds transformation cost
            if (!sameNode)
            {
                curCost++;
            }

            var children1 = new List <ITreeProgram <TOutput> >(subProg1.Input);
            var children2 = new List <ITreeProgram <TOutput> >(subProg2.Input);

            // try to align children if one (or both) function are commutative
            if (subProg1 is ICommutativeTreeProgram <TOutput> )
            {
                CollectionUtil.Align(children2, children1);
            }
            else if (subProg2 is ICommutativeTreeProgram <TOutput> )
            {
                CollectionUtil.Align(children1, children2);
            }

            // iterate recursively through both sub-programs' children in parallel
            var maxNumChildren = Math.Max(children1.Count, children2.Count);

            for (var i = 0; i < maxNumChildren; i++)
            {
                // advances indexes if corresponding child exists
                var prevIdx1 = children1.Count > i ? idx1 + 1 : uint.MaxValue;
                var prevIdx2 = children2.Count > i ? idx2 + 1 : uint.MaxValue;

                GetEditCost(subProgs1, subProgs2, ref prevIdx1, ref prevIdx2, ref curCost, ref totalCost);

                // updates indexes based on search
                idx1 = prevIdx1 == uint.MaxValue ? idx1 : prevIdx1;
                idx2 = prevIdx2 == uint.MaxValue ? idx2 : prevIdx2;
            }
        }