public FCNode MakeCopy(bool setPromoted = false, bool keepPointers = false, int prevAugmentedIndex = -1) { FCNode ret = new FCNode(BaseCoordNode, Dimension, Index, setPromoted, prevAugmentedIndex); if (keepPointers) { ret.NextNode = NextNode; ret.PreviousNode = PreviousNode; } return(ret); }
private void SetFCTransformationMatrix(int unitFracDen, bool print = false) { /** * Copy coordNode matrix into FCNode matrix, perform fractional cascading * transformation * * Parameter: * unitFracDen: denominator of the unit fraction indicating the size of the * subset of promoted list (d-1)' into list d' */ NodeMatrixPrime = new FCNode[k][]; // Convert coordNodes -> FCNodes if (print) { Console.WriteLine( "Instantiating (not-yet-promoted) FCNodes from coordNode data."); } for (int i = 0; i < k; i++) { NodeMatrixPrime[i] = new FCNode[n]; for (int j = 0; j < n; j++) { CoordNode thisCoordNode = InputCoordMatrix[i][j]; FCNode thisFCNode = new FCNode(thisCoordNode, (i + 1), j); NodeMatrixPrime[i][j] = thisFCNode; } } // Begin Fractional Cascading Transformation if (print) { Console.WriteLine( "Performing Fractional Cascading transformation on FCNode matrix."); } // Perform transformation on all lists in reverse order // Re. i = (k-2): as nodes are always promoted from higher dimensions into // lower ones, for (highest dim) k, list(k) = list(k') for (int i = k - 2; i >= 0; i--) { NodeMatrixPrime[i] = BuildListPrime(NodeMatrixPrime[i], NodeMatrixPrime[i + 1], unitFracDen); } }
private FCNode[] BuildListPrime(FCNode[] FCNodeList1, FCNode[] FCNodeList2, int unitFracDen) { /** * Combine all elements from fcNodeListOne and a fraction of the values from * fcNodeListTwo to a new list of FCNode. * * fcNodeListOne and fcNodeListTwo must be ordered according to their data * * Note: FCNodeList1 = list(i-1)' * FCNodeList2 = list(i) */ // Nested function to handle pointer assignment FCNode lastPromotedNode = null; FCNode lastNotPromotedNode = null; void SetPointers(FCNode currentNode) { // Assign prev and next pointers to closest non-promoted nodes if (currentNode.IsPromoted()) { lastPromotedNode = currentNode; currentNode.SetPrevPointer(lastNotPromotedNode); if (lastNotPromotedNode != null) { if (lastNotPromotedNode.GetNextPointer() == null) { lastNotPromotedNode.SetNextPointer(currentNode); } } } else // Assign prev and next pointers to closest promoted nodes { lastNotPromotedNode = currentNode; currentNode.SetPrevPointer(lastPromotedNode); if (lastPromotedNode != null) { if (lastPromotedNode.GetNextPointer() == null) { lastPromotedNode.SetNextPointer(currentNode); } } } currentNode.SetPrime(); } // Instantiate promoted list int numPromotedNodes = (int)(Math.Ceiling(FCNodeList2.Length / (double)unitFracDen)); FCNode[] FCNodeListPrime = new FCNode[n + numPromotedNodes]; // Populate w/ every 2nd elem in FCNodeList2 to be merged into FCNodeListPrime FCNode[] nodesToPromote = new FCNode[numPromotedNodes]; int c = 0; // index counter for nodesToPromote int d = 0; // index counter for FCNodeList1 int j = 0; // index counter for FCNodeListPrime for (int i = 0; i < FCNodeList2.Length; i += unitFracDen) { // It is essential that nodes be copied from here because this is the only // state at which we can easily both store their locations in their // previous lists and flag them as promoted. nodesToPromote[c++] = FCNodeList2[i].MakeCopy(setPromoted: true, prevAugmentedIndex: i); } // Perform Fractional Cascading transformation // -> Merge elements from nodesToPromote and FCNodeList1 into FCNodeListPrime // -> For each node, point to the previous and next foreign nodes // --> ie. prev and next nodes not present in initial list of given nod c = 0; while (c < nodesToPromote.Length && d < FCNodeList1.Length) { if (FCNodeList1[d].GetData() < nodesToPromote[c].GetData()) { FCNodeListPrime[j] = FCNodeList1[d++].MakeCopy(); } else { FCNodeListPrime[j] = nodesToPromote[c++]; } SetPointers(FCNodeListPrime[j]); j++; } // Add leftover values to augmented list: while (c < nodesToPromote.Length) { FCNodeListPrime[j] = nodesToPromote[c++]; SetPointers(FCNodeListPrime[j]); j++; } while (d < n) { FCNodeListPrime[j] = FCNodeList1[d++].MakeCopy(); SetPointers(FCNodeListPrime[j]); j++; } return(FCNodeListPrime); }
public void SetPrevPointer(FCNode prev) { PreviousNode = prev; }
public void SetNextPointer(FCNode next) { NextNode = next; }
private FCNode FindNodeFromPointerRange(FCNode dataNode, int targetDimension) { /** * Find and search a range of indices for the FCNode with the target data value * at the target dimension. * * Finding range: * DataNode comes from targetDimension - 1 . DataNode contains pointers to * FCNodes from the augmented list of the next dimension (TargetDimension). * The search range is between the locations of DataNode.prev and * DataNode.next in the augmented list in the TargetDimension. */ int targetData = dataNode.GetData(); FCNode prevNode = dataNode.GetPrevPointer(); FCNode nextNode = dataNode.GetNextPointer(); // Find range int lowRange, highRange; int targetDimIndex = targetDimension - 1; if (prevNode == null) { lowRange = 0; } else { lowRange = prevNode.GetPreviouslyAugmentedIndex(); } if (nextNode == null) { highRange = NodeMatrixPrime[targetDimIndex].Length; } else { highRange = nextNode.GetPreviouslyAugmentedIndex(); } IEnumerable <int> range = Enumerable.Range(lowRange, highRange - lowRange); // Search range bool found = false; foreach (int j in range) { dataNode = NodeMatrixPrime[targetDimIndex][j]; if (TargetNodeCheck(dataNode, targetData, targetDimension)) { found = true; break; } } if (!(found)) { throw new Exception("Can't find node with data " + targetData + " in dimension: " + targetDimension + " during fractional cascading search"); } return(dataNode); }
private bool TargetNodeCheck(FCNode node, int targetData, int targetDimension) { return(node != null && node.GetData() == targetData && node.GetDim() == targetDimension); }
public Dictionary <int, int> FractionalCascadingSearch(int data) { /** * Perform binary search to find data in first dimension. Then iteratively use * the previous and/or next pointers to search the (tiny) range of the next * dimension given by the prev and next node pointers */ BinarySearchNodes bsn = new BinarySearchNodes(); // Return dictionary w/ key=dimension, pair=location in dimension Dictionary <int, int> locationsOfData = new Dictionary <int, int>(); // Other variables we'll need FCNode dataNode = null; int dataIndex; int currentDim = 1; // Find data in first dimension dataIndex = bsn.BinarySearch(NodeMatrixPrime[0], data, 0); dataNode = NodeMatrixPrime[0][dataIndex]; // Ensure that dataNode is in the correct dimension - if not check neighbors if (dataNode.GetDim() != currentDim) { FCNode next = dataNode.GetNextPointer(); FCNode prev = dataNode.GetPrevPointer(); if (TargetNodeCheck(next, data, currentDim)) { dataNode = next; } else if (TargetNodeCheck(prev, data, currentDim)) { dataNode = prev; } else { string errorMsg = "Cannot locate data in augmented list 1'\n" + $"DataNode: {dataNode}\nIndex neighbor left:\t" + NodeMatrixPrime[0][dataIndex - 1] + "\nIndex neighbor right:\t" + NodeMatrixPrime[0][dataIndex + 1] + $"\nNextNode: {next}nPrevNode: {prev}"; throw new Exception(errorMsg); } } if (k < nLimit) // This takes up too much memory // Assign first dimension location in return dictionary { locationsOfData[currentDim] = dataNode.GetAttr(1); } for (int i = 1; i < NodeMatrixPrime.Length; i++) { // Walk through promoted node pointers, starting with the list 2' until // list (k)' currentDim++; dataNode = FindNodeFromPointerRange(dataNode, currentDim); if (k < nLimit) { locationsOfData[currentDim] = dataNode.GetAttr(1); } } return(locationsOfData); }