public IgnoreIdenticalBeginningAndEndCorrelaterWrapper(ICorrelater <T> innerCorrelater) { this.innerCorrelater = innerCorrelater; innerCorrelater.OnProgressUpdate += (p, t) => OnProgressUpdate?.Invoke(p, t); if (innerCorrelater is IContinuousCorrelater <T> continuousCorrelater) { continuousCorrelater.OnResultUpdate += r => OnResultUpdate?.Invoke(r); } }
public PatienceDiffCorrelater() { if (default(T) != null && typeof(T) != typeof(char)) { throw new EnumerableCorrelaterException($"{nameof(T)} must be nullable or a char"); } innerCorrelater.OnProgressUpdate += (p, t) => OnProgressUpdate?.Invoke(p, t); innerCorrelater.OnResultUpdate += r => OnResultUpdate?.Invoke(r); }
/// <summary> /// A certain stretch of the two chunks - which includes the end of the previous chunk, and the beginning of the current chunk, is considered the chunks "edge". /// We'll correlate this edge separately, to prevent loosing matches between chunks. /// </summary> private void AddEdge(int startFromIndexOnPreviousResult, int goUpToIndexOnCurrentResult, CorrelaterResult <T> currentResult, CorrelaterResult <T> previousResult, List <T> list1, List <T> list2, CancellationToken cancellationToken) { var collection1 = GetEdgeCollection(previousResult.BestMatch1, currentResult.BestMatch1, startFromIndexOnPreviousResult, goUpToIndexOnCurrentResult); var collection2 = GetEdgeCollection(previousResult.BestMatch2, currentResult.BestMatch2, startFromIndexOnPreviousResult, goUpToIndexOnCurrentResult); var result = innerCorrelater.Correlate(collection1, collection2, cancellationToken); AddRange(result.BestMatch1, list1, 0, result.BestMatch1.Length); AddRange(result.BestMatch2, list2, 0, result.BestMatch2.Length); OnResultUpdate?.Invoke(GetPartualResult(result, 0, result.BestMatch1.Length)); }
public CorrelaterResult <T> Merge(List <Task <CorrelaterResult <T> > > results) { var bestMatch1 = new List <T>(); var bestMatch2 = new List <T>(); var distance = 0L; var i = 0; foreach (var result in results.Select(t => t.Result)) { OnProgressUpdate?.Invoke(++i, results.Count); OnResultUpdate?.Invoke(result); bestMatch1.AddRange(result.BestMatch1); bestMatch2.AddRange(result.BestMatch2); distance += result.Distance; } return(new CorrelaterResult <T>(distance, bestMatch1.ToArray(), bestMatch2.ToArray())); }
private void AddFinalEdge(int addedUpTo, CorrelaterResult <T> result, List <T> list1, List <T> list2) { var length = Math.Max(0, result.BestMatch1.Length - addedUpTo); var array1 = new T[length]; var array2 = new T[length]; for (int i = addedUpTo; i < result.BestMatch1.Length; i++) { array1[i - addedUpTo] = result.BestMatch1[i]; } for (int i = addedUpTo; i < result.BestMatch2.Length; i++) { array2[i - addedUpTo] = result.BestMatch2[i]; } list1.AddRange(array1); list2.AddRange(array2); OnResultUpdate?.Invoke(new CorrelaterResult <T>(0, array1, array2)); }
// When connecting section A with section B, the Reduce method tries to better connect the "edges" of A and B. private CorrelaterResult <T> Reduce(List <Task <CorrelaterResult <T> > > resultTasks, CancellationToken cancellationToken) { var list1 = new List <T>(); var list2 = new List <T>(); var distance = 0L; var endEdgeIndex = -1; for (var i = 0; i < resultTasks.Count; i++) { var result = resultTasks[i].Result; var startEdgeIndex = i > 0 ? GetStartEdgeIndex(resultTasks[i].Result) : 0; if (i > 0) { AddEdge(endEdgeIndex, startEdgeIndex, result, resultTasks[i - 1].Result, list1, list2, cancellationToken); } endEdgeIndex = GetEndEdgeIndex(result); distance += result.Distance; if (maxDistance.HasValue && distance > maxDistance.Value) { return(null); } AddRange(result.BestMatch1, list1, startEdgeIndex, endEdgeIndex); AddRange(result.BestMatch2, list2, startEdgeIndex, endEdgeIndex); OnResultUpdate?.Invoke(GetPartualResult(result, startEdgeIndex, endEdgeIndex)); OnProgressUpdate?.Invoke(i + 1, resultTasks.Count); if (i == resultTasks.Count - 1) { AddFinalEdge(Math.Max(endEdgeIndex, startEdgeIndex), result, list1, list2); } } return(new CorrelaterResult <T>(distance, list1.ToArray(), list2.ToArray())); }
public CorrelaterResult <T> Correlate(IEnumerable <T> collection1, IEnumerable <T> collection2, CancellationToken cancellationToken = default) { var collection1Wrapper = collection1.ToCollectionWrapper(); var collection2Wrapper = collection2.ToCollectionWrapper(); var startIndex = GetFirstNotEqualIndex(collection1Wrapper, collection2Wrapper, cancellationToken); var endIndexes = GetLastNotEqualIndexes(collection1Wrapper, collection2Wrapper, startIndex, cancellationToken); if (startIndex > 0) { OnResultUpdate?.Invoke(new CorrelaterResult <T>(0, collection1Wrapper.Take(startIndex).ToArray(), collection2Wrapper.Take(startIndex).ToArray())); } var innerCorrelaterResult = innerCorrelater.Correlate( new OffsetCollectionWrapper <T>(collection1Wrapper, startIndex, endIndexes.Item1), new OffsetCollectionWrapper <T>(collection2Wrapper, startIndex, endIndexes.Item2), cancellationToken); var result = CreateResult(collection1Wrapper, collection2Wrapper, startIndex, endIndexes, innerCorrelaterResult); UpdateEndOfResult(startIndex, result, collection1Wrapper, endIndexes.Item1); return(result); }