public bool EqualsRegardlessOrder(IIndices indices) { return(indices.Size() == 0); }
public StructureOfContractions(Tensor[] data, int differentIndicesCount, IIndices freeIndices) { //Names (names with type, see IndicesUtils.getNameWithType() ) of all indices in this multiplication //It will be used as index name -> index index [0,1,2,3...] mapping int[] upperIndices = new int[differentIndicesCount], lowerIndices = new int[differentIndicesCount]; //This is sorage for intermediate information about indices, used in the algorithm (see below) //Structure: // ulong[] upperInfo = new ulong[differentIndicesCount], lowerInfo = new ulong[differentIndicesCount]; //This is for generalization of algorithm //indices[0] == lowerIndices //indices[1] == lowerIndices int[][] indices = { lowerIndices, upperIndices }; //This is for generalization of algorithm too //info[0] == lowerInfo //info[1] == lowerInfo ulong[][] info = { lowerInfo, upperInfo }; //Pointers for lower and upper indices, used in algorithm //pointer[0] - pointer to lower //pointer[1] - pointer to upper int[] pointer = new int[2]; //Allocating array for results, one contraction for each tensor contractions = new long[data.Length][]; //There is one dummy tensor with index -1, it represents fake //tensor contracting with whole Product to leave no contracting indices. //So, all "conractions" with this dummy "contraction" looks like a scalar //product. (sorry for English) freeContractions = new long[freeIndices.Size()]; uint state; uint index; uint i; //Processing free indices = creating contractions for dummy tensor for (i = 0; i < freeIndices.Size(); ++i) { index = freeIndices[i]; //Inverse state (because it is state of index at (??) dummy tensor, //contracted with this free index) state = 1 - IndicesUtils.getStateInt(index); //Important: info[state][pointer[state]] = dummyTensorInfo; indices[state][pointer[state]++] = IndicesUtils.GetNameWithType(index); } int tensorIndex; for (tensorIndex = 0; tensorIndex < data.Length; ++tensorIndex) { //Main algorithm IIndices tInds = data[tensorIndex].Indices; short[] diffIds = tInds.GetDiffIds(); //FUTURE move to other place if (tInds.Size() >= 0x10000) { throw new InvalidOperationException("Too many indices!!! max count = 2^16"); } for (uint j = 0; j < tInds.Size(); ++j) { index = tInds[j]; state = IndicesUtils.getStateInt(index); info[state][pointer[state]] = packToLong(tensorIndex, diffIds[j], j); indices[state][pointer[state]++] = IndicesUtils.GetNameWithType(index); } //Result allocation contractions[tensorIndex] = new long[tInds.Size()]; } //Here we can use unstable sorting algorithm (all indices are different) ArraysUtils.quickSort(indices[0], info[0].Select(u => (int)u).ToArray()); ArraysUtils.quickSort(indices[1], info[1].Select(u => (int)u).ToArray()); //Calculating connected components var infoTensorIndicesFrom = infoToTensorIndices(lowerInfo); var infoTensorIndicesTo = infoToTensorIndices(upperInfo); uint shift = 0; uint last = 0; for (i = 0; i < infoTensorIndicesFrom.Length; ++i) { if (infoTensorIndicesFrom[i] == -1 || infoTensorIndicesTo[i] == -1) { Array.Copy(infoTensorIndicesFrom, last, infoTensorIndicesFrom, last - shift, i - last); Array.Copy(infoTensorIndicesTo, last, infoTensorIndicesTo, last - shift, i - last); last = i + 1; ++shift; } } Array.Copy(infoTensorIndicesFrom, last, infoTensorIndicesFrom, last - shift, i - last); Array.Copy(infoTensorIndicesTo, last, infoTensorIndicesTo, last - shift, i - last); infoTensorIndicesFrom = Arrays.copyOf(infoTensorIndicesFrom, (int)(infoTensorIndicesFrom.Length - shift)); infoTensorIndicesTo = Arrays.copyOf(infoTensorIndicesTo, (int)(infoTensorIndicesTo.Length - shift)); int[] components = GraphUtils.CalculateConnectedComponents(infoTensorIndicesFrom, infoTensorIndicesTo, data.Length); componentCount = components[components.Length - 1]; this.components = Arrays.copyOfRange(components, 0, components.Length - 1); //<-- Here we have mature info arrays Debug.Assert(indices[0].SequenceEqual(indices[1])); int freePointer = 0; int indexIndex; for (i = 0; i < differentIndicesCount; ++i) { //Contractions from lower to upper tensorIndex = (int)(0xFFFFFFFFL & (info[0][i] >> 16)); //From tensor index indexIndex = (int)(0xFFFFL & (info[0][i] >> 48)); ulong contraction = (0xFFFFFFFFFFFF0000L & (info[1][i] << 16)) | (0xFFFFL & info[0][i]); if (tensorIndex == -1) { freeContractions[freePointer++] = (long)contraction; } else { contractions[tensorIndex][indexIndex] = (long)contraction; } //Contractions from upper to lower tensorIndex = (int)(0xFFFFFFFFL & (info[1][i] >> 16)); //From tensor index indexIndex = (int)(0xFFFFL & (info[1][i] >> 48)); contraction = (0xFFFFFFFFFFFF0000L & (info[0][i] << 16)) | (0xFFFFL & info[1][i]); if (tensorIndex == -1) { freeContractions[freePointer++] = (long)contraction; } else { contractions[tensorIndex][indexIndex] = (long)contraction; } } }