void buildTree(CausalSetSystemBlock entryBlock) { // store it for later reference for calculating the global energy unmodifiedRootSystemBlock = entryBlock; rootRewriteTreeElement = new RewriteTreeElement(); buildRewriteTreeRecursive(rootRewriteTreeElement, entryBlock.copyDeep()); }
// creates a new block with the content as the fused nodes and fuses the nodes in the "entryBlock" and returns the created "CausalSystemBlock" which contains all fused nodes on the next level // entryblock doesn't get modified static public CausalSetSystemBlock fuse(CausalSetSystemBlock entryBlock, out CausalSetSystemBlock modifiedEntryBlock, IList <uint> indices) { CausalSetSystemBlock modifiedEntryBlock_localVar = entryBlock.copyDeep(); CausalSetSystemBlock higherLevelBlock = new CausalSetSystemBlock(); // fill higherLevelBlock with as many nodes as required foreach (uint iterationIndex in indices) { CausalSetNode createdNode = new CausalSetNode(); createdNode.nodeIndexInParentSystemBlock = iterationIndex; higherLevelBlock.nodes.Add(createdNode); higherLevelBlock.indirectionArray.Add(higherLevelBlock.getNewIndirectionNumber()); } // translates the index in entryBlock to the index in higherLevelBlock Dictionary <uint, uint> indexToElementInHigherLevelBlock = new Dictionary <uint, uint>(); for (uint i = 0; i < indices.Count; i++) { uint redirectedIndex = indices[(int)i]; indexToElementInHigherLevelBlock[redirectedIndex] = i; } // rewire from entryBlock the subnetwork to HigherLevelBlock foreach (Tuple <uint, CausalSetNode> iterationIndexAndNodePair in indices.Select(index => new Tuple <uint, CausalSetNode>(index, modifiedEntryBlock_localVar.getNodeByIndex(index)))) { uint higherLevelBlock_index = indexToElementInHigherLevelBlock[iterationIndexAndNodePair.Item1]; var nextValidIndicesFromIterationNode = iterationIndexAndNodePair.Item2.next .Select(nextIndirection => modifiedEntryBlock_localVar.translateIndirectIndexToIndex(nextIndirection)) .Where(index => indexToElementInHigherLevelBlock.ContainsKey(index)); // if the node points to an node which is not in nextLevelBlock then we ignore it foreach (uint iterationNextValidIndexFromIterationNode in nextValidIndicesFromIterationNode) { uint higherLevelBlock_nextIndex = indexToElementInHigherLevelBlock[iterationNextValidIndexFromIterationNode]; // make sure that the indirection is an identity // only this way we don't have to do an inverse lookup to get the CausalIndirectionIndex Ensure.ensureHard(higherLevelBlock.translateIndirectIndexToIndex(new CausalIndirectionIndex(higherLevelBlock_nextIndex)) == higherLevelBlock_nextIndex); higherLevelBlock.nodes[(int)higherLevelBlock_index].next.Add(new CausalIndirectionIndex(higherLevelBlock_nextIndex)); } } // transfer global index // global indices of fused nodes get reset to null by fuse so we ignore them for (uint i = 0; i < indices.Count; i++) { uint entryBlockIndex = indices[(int)i]; uint higherLevelBlock_index = indexToElementInHigherLevelBlock[entryBlockIndex]; higherLevelBlock.nodes[(int)higherLevelBlock_index].globalIndex = modifiedEntryBlock_localVar.nodes[(int)entryBlockIndex].globalIndex; } // now do the fuse uint fuseAsIndirectionNumber = modifiedEntryBlock_localVar.getNewIndirectionNumber(); modifiedEntryBlock_localVar.fuse(indices, fuseAsIndirectionNumber); // add fused node modifiedEntryBlock_localVar.nodes.Add(new CausalSetNode(higherLevelBlock)); // remove fused nodes and rewire indirectionArray accordingly indices.ToList().Sort(); var reversedSortedIndices = indices.Reverse(); foreach (uint iterationNodeIndex in reversedSortedIndices) { // redirect all indices pointing at the element behind the removed one to one before it modifiedEntryBlock_localVar.indirectionArray = modifiedEntryBlock_localVar.indirectionArray.Select(v => v > iterationNodeIndex ? v - 1 : v).ToList(); modifiedEntryBlock_localVar.nodes.RemoveAt((int)iterationNodeIndex); } modifiedEntryBlock = modifiedEntryBlock_localVar; return(higherLevelBlock); }