/// <summary> /// Method to get the nodes of a specic level /// </summary> /// <param name="level"></param> /// <returns></returns> public IList <SbnNode> GetNodesOfLevel(int level) { if (level < 1 || level > NumLevels) { throw new ArgumentOutOfRangeException("level"); } var start = (int)Math.Pow(2, level - 1); var end = 2 * start - 1; return(NumPySlicing.GetRange(Nodes, start, end, 1)); }
//private class SbnBinEnumerator : IEnumerator<SbnBin> //{ // private readonly SbnTree _tree; // private SbnNode _currentNode; // private SbnBin _currentBin, _lastBin; // private bool _finished; // public SbnBinEnumerator(SbnTree tree) // { // _tree = tree; // } // public void Dispose() // { // } // public bool MoveNext() // { // if (_finished) // return false; // _lastBin = _currentBin; // var res = SeekNextBin(1); // Debug.Assert(!ReferenceEquals(_lastBin, _currentBin)); // return res; // } // bool SeekNextBin(int depth) // { // Debug.Assert(depth < 1000); // if (_currentNode == null) // { // _currentNode = _tree.Nodes[1]; // if (_currentNode.FirstBin == null) // return SeekNextBin(depth+1); // } // if (_currentBin == null) // { // _currentBin = _currentNode.FirstBin; // if (_currentBin == null) // { // if (_currentNode.Nid == _tree.LastLeafNodeId) // { // _finished = true; // return false; // } // _currentNode = _tree.Nodes[_currentNode.Nid + 1]; // return SeekNextBin(depth + 1); // } // return true; // } // _currentBin = _currentBin.Next; // if (_currentBin == null) // { // if (_currentNode.Nid == _tree.LastLeafNodeId) // { // _finished = true; // return false; // } // _currentNode = _tree.Nodes[_currentNode.Nid + 1]; // return SeekNextBin(depth + 1); // } // return true; // } // public void Reset() // { // _currentNode = null; // _currentBin = null; // _finished = false; // } // public SbnBin Current { get { return _currentBin; } } // object IEnumerator.Current // { // get { return Current; } // } //} /// <summary> /// Method to compute the number of features in a given level /// </summary> /// <param name="level">The level</param> /// <returns>The number of features</returns> public int FeaturesInLevel(int level) { // return the number of features in a level var start = (int)Math.Pow(2, level - 1); var end = 2 * start - 1; var featureCount = 0; foreach (var n in NumPySlicing.GetRange(Nodes, start, end - start + 1)) { featureCount += n.FeatureCount; } return(featureCount); }
/// <summary> /// Method to compact this <see cref="SbnTree"/>. /// </summary> private void CompactSeamFeatures() { // the mystery algorithm - compaction? optimization? obfuscation? if (NumLevels < 4) { return; } var start = FirstLeafNodeId / 2 - 1; if (start < 3) { start = 3; } var end = start / 8; if (end < 1) { end = 1; } foreach (var node in NumPySlicing.GetRange(Nodes, start, end, -1)) { var id = node.Nid; var children = NumPySlicing.GetRange(Nodes, id * 2, 2); foreach (var child in children) { // There are no items to pull up if (child.FeatureCount == 0) { continue; } var cid = child.Nid; var grandchildren = NumPySlicing.GetRange(Nodes, cid * 2, 2); var gccount = 0; foreach (var gcnode in grandchildren) { gccount += gcnode.FeatureCount; } //Debug.WriteLine("Node {0} has {1} GC", id, gccount); if (gccount == 0) { //Debug.WriteLine("Slurping {0} features from node {1}", child.AllFeatures().Count, child.id); //node.features.AddRange(child.features); // this is weird but it works if (child.FeatureCount < 4) { if (node.FirstBin == null) { node.FirstBin = new SbnBin(); } //for (var i = 0; i < child.FeatureCount; i++) //{ // //node.LastBin.AddFeature(child.FirstBin[i]); // node.LastBin.AddFeature(child.RemoveAt(0)); //} while (child.FeatureCount > 0) { node.LastBin.AddFeature(child.RemoveAt(0)); } //Debug.Assert(child.FeatureCount == 0); //child.FirstBin = null; } } } } Built = true; }