/// <summary> /// Set Nv/Dv, SNv/SDv and Depth values from given interval. /// </summary> /// <param name="source">left/right bounds specified as (nv/dv:snv/sdv) for nested intervals encoding. </param> public void SetFromInterval(IIntervalQuadruple source) { this.Nv = source.Nv; this.Dv = source.Dv; this.SNv = source.SNv; this.SDv = source.SDv; }
/// <summary> /// Initializes a new instance of the <see cref="TreeEntry"/> class. /// Using bounds given by <see cref="IIntervalQuadruple"/>. /// </summary> /// <param name="bounds">left/right bounds specified as (nv/dv:snv/sdv) for nested intervals encoding. </param> public TreeEntry(IIntervalQuadruple bounds) { this.Depth = bounds.Depth; this.Nv = bounds.Nv; this.Dv = bounds.Dv; this.SNv = bounds.SNv; this.SDv = bounds.SDv; }
/// <summary> /// Multiply matrix to Tree Entry interval values. /// </summary> /// <param name="matrix">2x2 Matrix to multiply.</param> /// <param name="target">Tree entry interval values. </param> /// <returns>Tree entry interval values multiplied with given matrix. </returns> public static IIntervalQuadruple MultiplyMatrixToInterval(long[,] matrix, IIntervalQuadruple target) { return(new IntervalQuadruple() { Nv = (matrix[0, 0] * target.Nv) + (matrix[0, 1] * target.Dv), Dv = (matrix[1, 0] * target.Nv) + (matrix[1, 1] * target.Dv), SNv = (matrix[0, 0] * target.SNv) + (matrix[0, 1] * target.SDv), SDv = (matrix[1, 0] * target.SNv) + (matrix[1, 1] * target.SDv), }); }
/// <summary> /// Build matrix with multipliers to use for subtree relocation (move) . /// </summary> /// <param name="sourceRoot">Tree entry to move descendants from. </param> /// <param name="targetRoot">Tree entry to move descendants into. </param> /// <param name="targetPosition">position number relative to other target children. </param> /// <returns>Matrix containing multipliers to use for subtree relocation. </returns> public static long[,] BuildSubtreeRelocationMatrix(IIntervalQuadruple sourceRoot, IIntervalQuadruple targetRoot, long targetPosition) { var sourceParent = sourceRoot.Depth == 1 ? null : GetParentInterval(sourceRoot); var sourcePosition = GetPositionByInterval(sourceParent, sourceRoot); return(MultiplyMatrix( MultiplyMatrix( IntervalToMatrix(targetRoot), PositionDifferenceMatrix(targetPosition, sourcePosition)), sourceParent == null ? GetIdentityMatrix() : IntervalToInverseMatrix(sourceParent))); }
private static long[,] IntervalToInverseMatrix(IIntervalQuadruple source) { return(new long[, ] { { -source.SDv, source.SNv, }, { source.Dv, -source.Nv, }, }); }
/// <summary> /// Get Root Tree Entry position. /// </summary> /// <param name="entry">Tree entry interval values. </param> /// <returns>Root Tree Entry position. </returns> public static long GetPositionByInterval(IIntervalQuadruple entry) { // Dv is always 1 for root entries. if (entry != null && entry.Dv != 1) { throw new ArgumentException($"Given entry nv/dv ({entry.Nv}/{entry.Dv}) does not identify root entry"); } // If entry is null return 0 which indicates index BEFORE FIRST element // For root entries Nv == index; return(entry?.Nv ?? 0); }
/// <summary> /// Build predicate selecting elements by it's positions relative to parent. /// </summary> /// <example> /// For path {2, 1, 3} it will select first root item, then first child of 2nd root item, then third child of 2nd root's first child. /// </example> /// <param name="positionsPath">Elements positions path relative to it's parent. Position indexes starting from 1.</param> /// <returns>Predicate selecting list of elements by given path. </returns> public static TreeFilter ElementsByPositionsPath(IEnumerable <long> positionsPath) { TreeFilter conditions = PredicateBuilder.False <TreeEntry>(); IIntervalQuadruple parentInterval = null; foreach (var position in positionsPath) { var childInterval = NestedIntervalMath.GetIntervalByPosition(parentInterval, position); conditions.Or(i => i.Nv == childInterval.Nv && i.Dv == childInterval.Dv); parentInterval = childInterval; } return(conditions); }
/// <summary> /// Get Tree Entry position relative to it's parent. /// </summary> /// <param name="parent">Tree entry parent interval values. </param> /// <param name="entry">Tree entry interval values. </param> /// <returns>Tree Entry position relative to it's parent. </returns> public static long GetPositionByInterval(IIntervalQuadruple parent, IIntervalQuadruple entry) { if (entry == null) { // If entry is null return 0 which indicates index BEFORE FIRST element return(0); } if (parent == null) { return(GetPositionByInterval(entry)); } return((entry.Nv - parent.Nv) / parent.SNv); }
/// <summary> /// Get Tree Entry interval values by it's position relative to parent. /// </summary> /// <param name="parent">parent item's tree entry interval. </param> /// <param name="index">Item's position relative to parent. </param> /// <returns>Tree entry interval values for an item. </returns> public static IIntervalQuadruple GetIntervalByPosition(IIntervalQuadruple parent, long index) { // returning intervals for root entry if parent is null if (parent == null) { return(GetIntervalByPosition(index)); } return(new IntervalQuadruple() { Depth = parent.Depth + 1, Nv = parent.Nv + (index * parent.SNv), Dv = parent.Dv + (index * parent.SDv), SNv = parent.Nv + ((index + 1) * parent.SNv), SDv = parent.Dv + ((index + 1) * parent.SDv), }); }
/// <summary> /// Get Tree Entry parent interval values. /// </summary> /// <param name="element">Tree entry interval values. </param> /// <returns>Tree Entry Parent interval values. </returns> public static IIntervalQuadruple GetParentInterval(IIntervalQuadruple element) { var parent = new IntervalQuadruple() { SNv = element.SNv - element.Nv, SDv = element.SDv - element.Dv, }; parent.Nv = element.Nv % parent.SNv; if (parent.SDv == 1) { parent.Dv = 1; } else { parent.Dv = element.Dv % parent.SDv; } parent.Depth = element.Depth - 1; return(parent); }