分形维数:装箱数、hausdorff、R^n 中的包装 space
Dimensions of fractals: boxing count, hausdorff, packing in R^n space
我想计算写成 n 维数组 0 和 1 的分形维数。它包括装箱计数、hausdorff 和包装尺寸。
我只知道如何对装箱计数维度进行编码(只计算 n 维矩阵中的 1,然后使用此公式:
boxing_count=-log(v)/log(n);
其中 n-number of 1's
和 n-space dimension (R^n)
这种方法模拟计算最小分辨率框 1 x 1 x ... x 1
,所以数字就像 limit eps->0
。您如何看待这个解决方案?
你有计算 hausdorff 或包装尺寸的想法(或代码)吗?
Hausdorff 维数和堆积维数是基于测度论的纯数学工具。它们在这种情况下具有出色的特性,但不太适合进行实验。简而言之,没有理由期望您可以基于对某个集合的单个矩阵近似来估计它们的值。
相比之下,盒计数维度非常适合数值研究。具体来说,让 N(e)
表示覆盖分形集所需的边长 e
的正方形数。您似乎知道,您的集合的盒子计数维度是 e->0
of
的限制
log(N(e))/log(1/e)
但是,我认为仅选择 e
的最小可用值通常不是一个好主意。据我所知,物理学文献中的标准解释是假定 N(e)
和 e
之间的关系应该在很宽的值范围内保持不变。计算盒计数维度的标准方法是计算 N(e)
,用于从几何上趋于零的序列中选择 e
的某些选择。然后,我们将一条线拟合到 N(e)
与 1/e
的对数对数图中的点。盒计数维度应该大约是该线的斜率。
例子
作为具体示例,以下 Python 代码生成描述分形结构的二进制矩阵。
import numpy as np
size = 1024
first_row = np.zeros(size, dtype=int)
first_row[int(size/2)-1] = 1
rows = np.zeros((int(size/2),size),dtype=int)
rows[0] = first_row
for i in range(1,int(size/2)):
rows[i] = (np.roll(rows[i-1],-1) + rows[i-1] + np.roll(rows[i-1],1)) % 2
m = int(np.log(size)/np.log(2))
rows = rows[0:2**(m-1),0:2**m]
我们可以通过简单地将每个 1 解释为黑色像素,将每个 0 解释为白色像素来查看分形结构。
import matplotlib.pyplot as plt
plt.matshow(rows, cmap = plt.cm.binary)
这个矩阵是一个很好的测试,因为它可以证明存在一个实际的限制对象,其分形维数为 log(1+sqrt(5))/log(2)
或大约 1.694,但它足够复杂,使得盒子计数估计有点棘手。
现在,这个矩阵是 512 行 x 1024 列;它自然分解为 2 个 512 x 512 的矩阵。每个自然分解为 4 个 256 x 256 的矩阵,依此类推。对于每个这样的分解,我们需要计算至少有一个非零的子矩阵的数量元素。我们可以按如下方式执行此分析:
cnts = []
for lev in range(m):
block_size = 2**lev
cnt = 0
for j in range(int(size/(2*block_size))):
for i in range(int(size/block_size)):
cnt = cnt + rows[j*block_size:(j+1)*block_size, i*block_size:(i+1)*block_size].any()
cnts.append(cnt)
data = np.array([(2**(m-(k+1)),cnts[k]) for k in range(m)])
data
# Out:
# array([[ 512, 45568],
# [ 256, 22784],
# [ 128, 7040],
# [ 64, 2176],
# [ 32, 672],
# [ 16, 208],
# [ 8, 64],
# [ 4, 20],
# [ 2, 6],
# [ 1, 2]])
现在,您的想法是简单地计算 log(45568)/log(512)
或大约 1.7195,这还算不错。我建议我们检查此数据的双对数图。
xs = np.log(data[:,0])
ys = np.log(data[:,1])
plt.plot(xs,ys, 'o')
这看起来确实接近于线性,表明我们可能希望我们的盒计数技术工作得相当好。不过,首先,排除一个看起来异常的点可能是合理的。事实上,这是这种方法的理想特征之一。方法如下:
plt.plot(xs,ys, 'o')
xs = xs[1:]
ys = ys[1:]
A = np.vstack([xs, np.ones(len(xs))]).T
m,b = np.linalg.lstsq(A, ys)[0]
def line(x): return m*x+b
ys = line(xs)
plt.plot(xs,ys)
m
# Out: 1.6902585379630133
嗯,结果看起来不错。特别是,这是一个明确的例子,表明这种方法 可以 比仅使用一个数据点的简单想法更有效。不过,公平地说,不难找到简单方法效果更好的示例。此外,这个集合足够规则,我们可以得到一些不错的结果。一般来说,人们不能真的期望盒子计数计算太可靠。
我想计算写成 n 维数组 0 和 1 的分形维数。它包括装箱计数、hausdorff 和包装尺寸。
我只知道如何对装箱计数维度进行编码(只计算 n 维矩阵中的 1,然后使用此公式:
boxing_count=-log(v)/log(n);
其中 n-number of 1's
和 n-space dimension (R^n)
这种方法模拟计算最小分辨率框 1 x 1 x ... x 1
,所以数字就像 limit eps->0
。您如何看待这个解决方案?
你有计算 hausdorff 或包装尺寸的想法(或代码)吗?
Hausdorff 维数和堆积维数是基于测度论的纯数学工具。它们在这种情况下具有出色的特性,但不太适合进行实验。简而言之,没有理由期望您可以基于对某个集合的单个矩阵近似来估计它们的值。
相比之下,盒计数维度非常适合数值研究。具体来说,让 N(e)
表示覆盖分形集所需的边长 e
的正方形数。您似乎知道,您的集合的盒子计数维度是 e->0
of
log(N(e))/log(1/e)
但是,我认为仅选择 e
的最小可用值通常不是一个好主意。据我所知,物理学文献中的标准解释是假定 N(e)
和 e
之间的关系应该在很宽的值范围内保持不变。计算盒计数维度的标准方法是计算 N(e)
,用于从几何上趋于零的序列中选择 e
的某些选择。然后,我们将一条线拟合到 N(e)
与 1/e
的对数对数图中的点。盒计数维度应该大约是该线的斜率。
例子
作为具体示例,以下 Python 代码生成描述分形结构的二进制矩阵。
import numpy as np
size = 1024
first_row = np.zeros(size, dtype=int)
first_row[int(size/2)-1] = 1
rows = np.zeros((int(size/2),size),dtype=int)
rows[0] = first_row
for i in range(1,int(size/2)):
rows[i] = (np.roll(rows[i-1],-1) + rows[i-1] + np.roll(rows[i-1],1)) % 2
m = int(np.log(size)/np.log(2))
rows = rows[0:2**(m-1),0:2**m]
我们可以通过简单地将每个 1 解释为黑色像素,将每个 0 解释为白色像素来查看分形结构。
import matplotlib.pyplot as plt
plt.matshow(rows, cmap = plt.cm.binary)
这个矩阵是一个很好的测试,因为它可以证明存在一个实际的限制对象,其分形维数为 log(1+sqrt(5))/log(2)
或大约 1.694,但它足够复杂,使得盒子计数估计有点棘手。
现在,这个矩阵是 512 行 x 1024 列;它自然分解为 2 个 512 x 512 的矩阵。每个自然分解为 4 个 256 x 256 的矩阵,依此类推。对于每个这样的分解,我们需要计算至少有一个非零的子矩阵的数量元素。我们可以按如下方式执行此分析:
cnts = []
for lev in range(m):
block_size = 2**lev
cnt = 0
for j in range(int(size/(2*block_size))):
for i in range(int(size/block_size)):
cnt = cnt + rows[j*block_size:(j+1)*block_size, i*block_size:(i+1)*block_size].any()
cnts.append(cnt)
data = np.array([(2**(m-(k+1)),cnts[k]) for k in range(m)])
data
# Out:
# array([[ 512, 45568],
# [ 256, 22784],
# [ 128, 7040],
# [ 64, 2176],
# [ 32, 672],
# [ 16, 208],
# [ 8, 64],
# [ 4, 20],
# [ 2, 6],
# [ 1, 2]])
现在,您的想法是简单地计算 log(45568)/log(512)
或大约 1.7195,这还算不错。我建议我们检查此数据的双对数图。
xs = np.log(data[:,0])
ys = np.log(data[:,1])
plt.plot(xs,ys, 'o')
这看起来确实接近于线性,表明我们可能希望我们的盒计数技术工作得相当好。不过,首先,排除一个看起来异常的点可能是合理的。事实上,这是这种方法的理想特征之一。方法如下:
plt.plot(xs,ys, 'o')
xs = xs[1:]
ys = ys[1:]
A = np.vstack([xs, np.ones(len(xs))]).T
m,b = np.linalg.lstsq(A, ys)[0]
def line(x): return m*x+b
ys = line(xs)
plt.plot(xs,ys)
m
# Out: 1.6902585379630133
嗯,结果看起来不错。特别是,这是一个明确的例子,表明这种方法 可以 比仅使用一个数据点的简单想法更有效。不过,公平地说,不难找到简单方法效果更好的示例。此外,这个集合足够规则,我们可以得到一些不错的结果。一般来说,人们不能真的期望盒子计数计算太可靠。