public double calculate(IEnumerable<KeyValuePair<double, double>> dataList) { double minY = Double.MaxValue, maxY = Double.MinValue; double minX = minY, maxX = maxY; foreach (var pair in dataList) { if (minY > pair.Value) minY = pair.Value; if (maxY < pair.Value) maxY = pair.Value; if (minX > pair.Key) minX = pair.Key; if (maxX < pair.Key) maxX = pair.Key; } m_bottomLeftY = minY; m_bottomLeftX = minX; return calculate(dataList, maxX, maxY); } public double calculate(IEnumerable<KeyValuePair<double, double>> dataList, double maxX, double maxY) { if( dataList.Count() < 2) return 0; for(int scaleNumber = StartSize; scaleNumber !=FinishSize; ++scaleNumber){ double XScale = (maxX - m_bottomLeftX) / scaleNumber; double YScale = (maxY - m_bottomLeftY) / scaleNumber; var enumerator = dataList.GetEnumerator(); fillBoxes( (ref double x, ref double y) => { var res = enumerator.MoveNext(); if (res) { x = enumerator.Current.Key; y = enumerator.Current.Value; } return res; }, XScale, YScale); int count = calculatedNumberBoxesAndReset(scaleNumber); if (count == 0) count = 1; m_boxesNumber[scaleNumber - StartSize] = Math.Log(count); } m_linearApproximator.approximate(m_scaleArgument, m_boxesNumber); return m_linearApproximator.resultPolinomal.a[1]; } double m_bottomLeftX, m_bottomLeftY;
void fillBoxes(GetDataDelegate dataIterator, double stepX, double stepY) { double prevX=0, prevY=0, targetX=0, targetY=0; dataIterator(ref prevX, ref prevY); int indexY = FinishSize, indexX = FinishSize; int currentIndexX= calculateIndex(m_bottomLeftX, stepX, prevX), currentIndexY =calculateIndex(m_bottomLeftY, stepY, prevY) ; m_Boxes[currentIndexY, currentIndexX] = true; double[] CrossPosition = new double[2]; while (dataIterator(ref targetX, ref targetY)) { if(prevX == targetX && prevY == targetY) continue; bool isBottom = targetY - prevY < 0; bool isLeft = targetX - prevX < 0; double a = (targetY - prevY) / (targetX - prevX), fracA=1/a; double b = targetY - a * targetX; double leftBorder = m_bottomLeftX + currentIndexX * stepX, bottomBorder = m_bottomLeftY + currentIndexY * stepY; CrossPosition[0] = (leftBorder + (isLeft ? 0 : stepX)) * a + b; CrossPosition[1] = (bottomBorder + (isBottom ? 0 : stepY) - b) * fracA; while ( (targetY < CrossPosition[0] == isBottom && Math.Abs(targetY - CrossPosition[0]) / stepY > 1E-9) || (targetX < CrossPosition[1] == isLeft && Math.Abs(targetX - CrossPosition[1]) / stepX > 1E-9) )// ? { if ( (bottomBorder - CrossPosition[0])/stepY <= 1E-9 && (CrossPosition[0] - bottomBorder - stepY)/stepY <= 1E-9) currentIndexX += isLeft ? -1 : 1; if ( (leftBorder-CrossPosition[1])/stepX <= 1E-9 && (CrossPosition[1] -leftBorder - stepX)/stepX <= 1E-9 ) currentIndexY += isBottom ? -1 : 1; m_Boxes[currentIndexY, currentIndexX] = true; leftBorder = m_bottomLeftX + currentIndexX * stepX; bottomBorder = m_bottomLeftY + currentIndexY * stepY; CrossPosition[0] = (leftBorder + (isLeft ? 0 : stepX)) * a + b; CrossPosition[1] = (bottomBorder + (isBottom ? 0 : stepY) - b) * fracA; } prevY = targetY; prevX = targetX; } }
public class MinkowskiDimension { public MinkowskiDimension(int startSize, int finishSzie) { StartSize = startSize; FinishSize = finishSzie; } public MinkowskiDimension() { } public int StartSize { get { return m_startSize; } set { m_startSize = value; if (m_startSize < m_finishSize) { m_scaleArgument = new double[m_finishSize - m_startSize]; for (int i = 0; i != m_scaleArgument.Count(); ++i) m_scaleArgument[i] = - Math.Log(m_startSize + i); m_boxesNumber = new double[m_scaleArgument.Count()]; } } } int m_startSize; public int FinishSize { get { return m_finishSize; } set { m_finishSize = value; m_Boxes = new bool[value, value]; if (m_startSize < m_finishSize) { m_scaleArgument = new double[m_finishSize - m_startSize]; for (int i = 0; i != m_scaleArgument.Count(); ++i) m_scaleArgument[i] = Math.Log(m_startSize + i); m_boxesNumber = new double[m_scaleArgument.Count()]; } } } int m_finishSize; double[] m_scaleArgument; double[] m_boxesNumber; public double calculate(IEnumerable<KeyValuePair<double, double>> dataList) { double minY = Double.MaxValue, maxY = Double.MinValue; double minX = minY, maxX = maxY; foreach (var pair in dataList) { if (minY > pair.Value) minY = pair.Value; if (maxY < pair.Value) maxY = pair.Value; if (minX > pair.Key) minX = pair.Key; if (maxX < pair.Key) maxX = pair.Key; } m_bottomLeftY = minY; m_bottomLeftX = minX; return calculate(dataList, maxX, maxY); } public double calculate(IEnumerable<KeyValuePair<double, double>> dataList, double maxX, double maxY) { if( dataList.Count() < 2) return 0; for(int scaleNumber = StartSize; scaleNumber !=FinishSize; ++scaleNumber){ double XScale = (maxX - m_bottomLeftX) / scaleNumber; double YScale = (maxY - m_bottomLeftY) / scaleNumber; var enumerator = dataList.GetEnumerator(); fillBoxes( (ref double x, ref double y) => { var res = enumerator.MoveNext(); if (res) { x = enumerator.Current.Key; y = enumerator.Current.Value; } return res; }, XScale, YScale); int count = calculatedNumberBoxesAndIbit(scaleNumber); if (count == 0) count = 1; m_boxesNumber[scaleNumber - StartSize] = Math.Log(count); } m_linearApproximator.approximate(m_scaleArgument, m_boxesNumber); return m_linearApproximator.resultPolinomal.a[1]; } double m_bottomLeftX, m_bottomLeftY; void fillBoxes(GetDataDelegate dataIterator, double stepX, double stepY) { double prevX=0, prevY=0, targetX=0, targetY=0; dataIterator(ref prevX, ref prevY); int indexY = FinishSize, indexX = FinishSize; int currentIndexX= calculateIndex(m_bottomLeftX, stepX, prevX), currentIndexY =calculateIndex(m_bottomLeftY, stepY, prevY) ; m_Boxes[currentIndexY, currentIndexX] = true; double[] CrossPosition = new double[2]; while (dataIterator(ref targetX, ref targetY)) { if(prevX == targetX && prevY == targetY) continue; bool isBottom = targetY - prevY < 0; bool isLeft = targetX - prevX < 0; double a = (targetY - prevY) / (targetX - prevX), fracA=1/a; double b = targetY - a * targetX; double leftBorder = m_bottomLeftX + currentIndexX * stepX, bottomBorder = m_bottomLeftY + currentIndexY * stepY; CrossPosition[0] = (leftBorder + (isLeft ? 0 : stepX)) * a + b; CrossPosition[1] = (bottomBorder + (isBottom ? 0 : stepY) - b) * fracA; while ( (targetY < CrossPosition[0] == isBottom && Math.Abs(targetY - CrossPosition[0]) / stepY > 1E-9) || (targetX < CrossPosition[1] == isLeft && Math.Abs(targetX - CrossPosition[1]) / stepX > 1E-9) )// ? { if ( (bottomBorder - CrossPosition[0])/stepY <= 1E-9 && (CrossPosition[0] - bottomBorder - stepY)/stepY <= 1E-9) currentIndexX += isLeft ? -1 : 1; if ( (leftBorder-CrossPosition[1])/stepX <= 1E-9 && (CrossPosition[1] -leftBorder - stepX)/stepX <= 1E-9 ) currentIndexY += isBottom ? -1 : 1; m_Boxes[currentIndexY, currentIndexX] = true; leftBorder = m_bottomLeftX + currentIndexX * stepX; bottomBorder = m_bottomLeftY + currentIndexY * stepY; CrossPosition[0] = (leftBorder + (isLeft ? 0 : stepX)) * a + b; CrossPosition[1] = (bottomBorder + (isBottom ? 0 : stepY) - b) * fracA; } prevY = targetY; prevX = targetX; } } int calculateIndex(double startvalue, double scale, double value) { double index = (value - startvalue) / scale; int intIndex = (int) index; return Math.Abs(index - intIndex) > 1E-9 || intIndex ==0 ? intIndex: intIndex -1; } int calculatedNumberBoxesAndIbit(int currentScaleSize) { int result=0; for (int i = 0; i != currentScaleSize; ++i) { for (int j = 0; j != currentScaleSize; ++j) { if (m_Boxes[i, j]){ ++result; m_Boxes[i, j] = false; } } } return result; } bool[,] m_Boxes; PolinomApproximation m_linearApproximator = new PolinomApproximation(1); }
[TestMethod] public void lineDimensionTest() { var m_calculator = new MinkowskiDimension(3, 10); var data = new List <KeyValuePair<double, double>>(); data.Add(new KeyValuePair<double, double>(0, 1)); data.Add(new KeyValuePair<double, double>(1, 5)); double result = m_calculator.calculate(data); if (Math.Abs(result - 1) > 1E-9) Assert.Fail(); data.Add(new KeyValuePair<double, double>(2, 9)); result = m_calculator.calculate(data); if (Math.Abs(result - 1) > 1E-9) Assert.Fail(); data.Clear(); data.Add(new KeyValuePair<double, double>(0, -1)); data.Add(new KeyValuePair<double, double>(1, -5)); data.Add(new KeyValuePair<double, double>(2, -9)); result = m_calculator.calculate(data); if (Math.Abs(result - 1) > 1E-9) Assert.Fail(); data.Clear(); data.Add(new KeyValuePair<double, double>(0, -1)); data.Add(new KeyValuePair<double, double>(0.5, -3)); data.Add(new KeyValuePair<double, double>(2, -9)); result = m_calculator.calculate(data); if (Math.Abs(result - 1) > 1E-9) Assert.Fail(); }
[TestMethod] public void squareDimensiontest() { var m_calculator = new MinkowskiDimension(3, 15); var data = new List<KeyValuePair<double, double>>(); data.Add(new KeyValuePair<double, double>(0, 1)); data.Add(new KeyValuePair<double, double>(1, 0)); data.Add(new KeyValuePair<double, double>(0, -1)); data.Add(new KeyValuePair<double, double>(-1, 0)); data.Add(new KeyValuePair<double, double>(0, 1)); double result = m_calculator.calculate(data); if (Math.Abs(result - 2) > 1E-9) Assert.Fail(); }
Source: https://habr.com/ru/post/264451/
All Articles