Ejemplo n.º 1
0
 public AlignmentNode(DiffOperation operation, double similarity, int nodeCount, [CanBeNull] AlignmentNode next)
 {
     Operation  = operation;
     Similarity = similarity;
     NodeCount  = nodeCount;
     Next       = next;
 }
        private AlignmentNode CalculateBestAlignment([NotNull] Dictionary <AlignmentKey, AlignmentNode> nodes, [NotNull] IList <T> collection1, int lower1, int upper1, [NotNull] IList <T> collection2, int lower2, int upper2)
        {
            var           key = new AlignmentKey(lower1, lower2);
            AlignmentNode result;

            if (nodes.TryGetValue(key, out result))
            {
                Assume.That(result != null);
                return(result);
            }

            if (lower1 == upper1 && lower2 == upper2)
            {
                result = new AlignmentNode(DiffOperation.Match, 0.0, 0, null);
            }
            else if (lower1 == upper1)
            {
                var restAfterInsert = CalculateBestAlignment(nodes, collection1, lower1, upper1, collection2, lower2 + 1, upper2);
                result = new AlignmentNode(DiffOperation.Insert, restAfterInsert.Similarity, restAfterInsert.NodeCount + 1, restAfterInsert);
            }
            else if (lower2 == upper2)
            {
                var restAfterDelete = CalculateBestAlignment(nodes, collection1, lower1 + 1, upper1, collection2, lower2, upper2);
                result = new AlignmentNode(DiffOperation.Delete, restAfterDelete.Similarity, restAfterDelete.NodeCount + 1, restAfterDelete);
            }
            else
            {
                // Calculate how the results will be if we insert a new element
                var restAfterInsert = CalculateBestAlignment(nodes, collection1, lower1, upper1, collection2, lower2 + 1, upper2);
                var resultInsert    = new AlignmentNode(DiffOperation.Insert, restAfterInsert.Similarity, restAfterInsert.NodeCount + 1, restAfterInsert);

                // Calculate how the results will be if we delete an element
                var restAfterDelete = CalculateBestAlignment(nodes, collection1, lower1 + 1, upper1, collection2, lower2, upper2);
                var resultDelete    = new AlignmentNode(DiffOperation.Delete, restAfterDelete.Similarity, restAfterDelete.NodeCount + 1, restAfterDelete);

                // Calculate how the results will be if we replace or modify an element
                var           restAfterChange = CalculateBestAlignment(nodes, collection1, lower1 + 1, upper1, collection2, lower2 + 1, upper2);
                double        similarity      = _SimilarityFunc(collection1[lower1], collection2[lower2]);
                AlignmentNode resultChange    = null;
                if (similarity >= _ModificationThreshold)
                {
                    resultChange = new AlignmentNode(DiffOperation.Modify, similarity + restAfterInsert.Similarity, restAfterChange.NodeCount + 1, restAfterChange);
                }

                // Then pick the operation that resulted in the best average similarity
                result = resultDelete;
                if (resultInsert.AverageSimilarity > result.AverageSimilarity)
                {
                    result = resultInsert;
                }
                if (resultChange?.AverageSimilarity > result.AverageSimilarity)
                {
                    result = resultChange;
                }
            }

            nodes[key] = result;
            return(result);
        }