public override void Start(CancellationToken token, Action <double> action) { double minPathLength = double.MaxValue; int[] minSequence = null; const int selected = 2; GeneralRepresentation representation = new GeneralRepresentation(_startPermutation.Length, selected); IndexEnumerator indexEnumerator = new IndexEnumerator(representation); int[] currentSequence = _startPermutation.ToArray(); while (!token.IsCancellationRequested) { // One local ring do { // Forcing delay for visualization if (_config.UseDelay) { Thread.Sleep(_config.DelayTime); } Helper.SwapPositions(currentSequence, indexEnumerator.CurrentCombination.Elements); var currentPathLength = _euclideanPath.GetPathLength(currentSequence, ClosedPath); if (currentPathLength < minPathLength) { minPathLength = currentPathLength; action?.Invoke(minPathLength); minSequence = currentSequence.ToArray(); _optimalSequence.OnNext(minSequence); // Stop on first optimum, something like greedy strategy break; } else { Helper.SwapPositions(currentSequence, indexEnumerator.CurrentCombination.Elements); } } while (indexEnumerator.SetNext()); // Continue on new ring starting from minimum path length of ancestor ring representation = new GeneralRepresentation(_startPermutation.Length, selected); indexEnumerator = new IndexEnumerator(representation); } _optimalSequence.OnCompleted(); }
protected override void DoInference() { var matrix = Param; var sizes1 = matrix.Sizes.ToList(); var sizes2 = matrix.Vectors[0].Sizes.ToList(); var c = 0; List <int> enumSize; IndexEnumerator enumerator; Matrix <T> result; switch (Mode) { case UnwrapMode.Discrete: enumSize = sizes1.ToList(); enumSize.AddRange(sizes2); result = new Matrix <T>(enumSize); enumerator = new IndexEnumerator(enumSize); while (enumerator.MoveNext()) { var subMatrix = matrix[enumerator.Current.Take(matrix.DimensionCount)]; var vector = subMatrix[enumerator.Current.Skip(matrix.DimensionCount)]; result.Vectors[c] = vector; c++; } Output = result; break; case UnwrapMode.Expand: enumSize = sizes1.ToList(); var finalSizes = sizes1.ToList(); while (finalSizes.Count < sizes2.Count) { finalSizes.Add(1); } for (var i = 0; i < sizes2.Count; i++) { finalSizes[finalSizes.Count - sizes2.Count + i] *= sizes2[i]; } result = new Matrix <T>(finalSizes); for (var i = 0; i < sizes2.Count; i++) { var size1Index = Math.Max(0, enumSize.Count - sizes2.Count) + i; enumSize.Insert(size1Index + 1, sizes2[i]); } enumerator = new IndexEnumerator(enumSize); while (enumerator.MoveNext()) { List <int> topIndex; List <int> subIndex; if (sizes1.Count > sizes2.Count) { topIndex = enumerator.Current.Take(sizes1.Count - sizes2.Count).ToList(); topIndex.AddRange(enumerator.Current.Skip(sizes1.Count - sizes2.Count) .Where((element, index) => index % 2 == 0)); subIndex = enumerator.Current.Skip(sizes1.Count - sizes2.Count) .Where((element, index) => index % 2 == 1).ToList(); } else { topIndex = enumerator.Current.Where((element, index) => index % 2 == 0).Take(sizes1.Count).ToList(); subIndex = enumerator.Current.Where((element, index) => index % 2 == 1).ToList(); subIndex.AddRange(enumerator.Current.Skip(sizes1.Count * 2)); } var subMatrix = matrix[topIndex]; var vector = subMatrix[subIndex]; result.Vectors[c] = vector; c++; } Output = result; break; default: throw new ArgumentOutOfRangeException(); } }
protected override void DoInference() { var matrix = Left; var other = Right; // Checks that two matrices have the same number of dimensions if (matrix.DimensionCount != other.DimensionCount) { throw new InvalidOperationException("The two matrixes must have the same number of dimensions"); } // Gets the sizes of the dimensions (other than the concatenated dimension) // And checks that they're all of the same size var sizeA = matrix.Sizes.Where((element, index) => index != DimensionIndex); var sizeB = other.Sizes.Where((element, index) => index != DimensionIndex); if (!sizeA.SequenceEqual(sizeB)) { throw new InvalidOperationException( $"The arrays must be of same size in all other dimensions than {DimensionIndex}"); } if (matrix.DimensionCount < DimensionIndex) { throw new InvalidOperationException( $"The matrixes are of dimension {matrix.DimensionCount}, cannot concatenate on dimension {DimensionIndex}. Max possible value is {matrix.DimensionCount}"); } // The resulting matrix size var resultSizes = matrix.Sizes.ToList(); // DimensionIndex < 0 if (DimensionIndex < 0) { // In this case, we add dimensions "before" var intermediarySizes = Enumerable.Repeat(1, DimensionIndex * -1 - 1).ToList(); intermediarySizes.Insert(0, 2); intermediarySizes.AddRange(resultSizes); resultSizes = intermediarySizes; } else // Otherwise, we add the two dimension sizes for the corresponding index { resultSizes[DimensionIndex] = resultSizes[DimensionIndex] + other.Sizes.ElementAt(DimensionIndex); } // The resulting matrix var result = new Matrix <T>(resultSizes); // We create an enumerator to iterate through our indices var indexEnumerator = new IndexEnumerator(resultSizes); if (DimensionIndex < 0) { for (var i = 0; i < matrix.VectorCount; i++) { result.Vectors[i] = matrix.Vectors[i]; } for (var i = matrix.VectorCount; i < matrix.VectorCount + other.VectorCount; i++) { result.Vectors[i] = other.Vectors[i - matrix.VectorCount]; } Output = result; return; } while (indexEnumerator.MoveNext()) { var currentIndexes = indexEnumerator.Current.ToList(); var fromMatrixIndex = currentIndexes.ToList(); Matrix <T> fromMatrix; if (DimensionIndex == -1) { switch (currentIndexes[0]) { case 0: fromMatrix = matrix; fromMatrixIndex.RemoveAt(0); break; case 1: fromMatrix = other; fromMatrixIndex.RemoveAt(0); break; default: throw new ArgumentOutOfRangeException(); } } else if (currentIndexes.ElementAt(DimensionIndex) >= matrix.Sizes.ElementAt(DimensionIndex)) { fromMatrix = other; fromMatrixIndex[DimensionIndex] = currentIndexes[DimensionIndex] - matrix.Sizes.ElementAt(DimensionIndex); } else { fromMatrix = matrix; } result[currentIndexes] = fromMatrix[fromMatrixIndex]; } Output = result; }
internal ElementEnumerator(ref NativeArray <T> slice) { Slice = slice; IndexEnumerator = new IndexEnumerator <T>(ref slice); }
protected override void DoInference() { var matrix = Param; // The size of the "from" dimension var sizeFrom = matrix.Sizes.ElementAt(DimensionFrom); // The size of the "to" dimension var sizeTo = matrix.Sizes.ElementAt(DimensionTo); // The final size of the "to" dimension, after flattening var finalSizeTo = sizeTo * sizeFrom; // The final size of the resulting matrix var finalSizes = new List <int>(matrix.Sizes) { [DimensionTo] = finalSizeTo }; finalSizes.RemoveAt(DimensionFrom); // The strategy here is quite simple. // // Our goal is to provide a new matrix that corresponds to the given // matrix with the "from" dimension flattened into the "two" dimension. // // Examples of flattening on a 3x3x3 matrix (read cube) // We can flatten the 3rd dimension into the 1st (lose width, gain depth) // We can flatten the 3rd dimension into the 2nd (lose width, gain height) // We can flatten the 2nd dimension into the 1st (lose height, gain depth) // We can flatten the 2nd dimension into the 3rd (lose height, gain width) // We can flatten the 1st dimension into the 1st (lose depth, gain width) // We can flatten the 1st dimension into the 3rd (lose depth, gain height) // // So we will have to do some kind of loop through our vectors. But in what order? // // Normally, when we iterate through a matrix, we do it // from the innermost dimension, towards the outermost dimension. // Eg. 000 -> 001 -> 010 -> 011 ... // // We will use the same strategy, but we will reorder the dimensions first. // Then we will iterate in the same way, but with our reordered dimensions. // So our initial dimensions are 0,1,2,3, ... // // If we want to flatten the 3rd dimension into the 1st dimension, our // ordering will be like so : 0,1,2,3 => 2,0,1,3 (or 0,2,1,3 depending on the flattening mode) // // We will create an iterator that will iterate through those indices like // they were normal indices, but we will then use a map between our reordered index // and our actual index to access the vectors in the desired order. // This will contain the reordered indexes var reorderedIndexes = new List <int>(); for (var i = 0; i < matrix.DimensionCount; i++) { reorderedIndexes.Add(i); } reorderedIndexes.RemoveAt(DimensionFrom); // This contains the index of the "to" dimension in our reordered index list var toOrderIndex = reorderedIndexes.IndexOf(DimensionTo); // Double dispatch, depending on mode switch (Mode) { case FlattenMode.Interpose: reorderedIndexes.Insert(toOrderIndex + 1, DimensionFrom); break; case FlattenMode.Extend: reorderedIndexes.Insert(toOrderIndex, DimensionFrom); break; default: throw new ArgumentOutOfRangeException(nameof(Mode), Mode, null); } // This contains the sizes of the dimension, in respect to our reordered indices var reorderedSizes = reorderedIndexes.Select(i => matrix.Sizes.ElementAt(i)).ToList(); // The enumartor that will iterate through these reordered indices var reorderedIndexEnumerator = new IndexEnumerator(reorderedSizes); // The resulting matrix var result = new Matrix <T>(finalSizes); // A counter, will help update the result matrix var c = 0; while (reorderedIndexEnumerator.MoveNext()) { // We select both the index of the reordered dimension, as well as // it's current step within that dimension var normalized = reorderedIndexEnumerator.Current.ToList() .Select((element, index) => new { element, index }) .ToList(); // We sort in respect to the initial order of the dimensions normalized.Sort((left, right) => Comparer <int> .Default.Compare(reorderedIndexes[left.index], reorderedIndexes[right.index])); // We set the resulting matrix vector to this current vector result.Vectors[c] = matrix[normalized.Select(arg => arg.element)]; c++; } Output = result; }