迭代函数系统
迭代函数系统(iterated function system,简称 IFS)是一族反复作用于点或集合的映射。对完备度量空间中的有限个严格压缩映射,把一个非空紧集的所有像合并,再重复这一操作,会收敛到唯一的非空紧吸引子。这个结论不要求不同像互不相交,也不要求映射保持相似形状。
一个可手算的例子是实数轴上的 与 。从单点集 出发,第一步得到 ,第二步得到 。这些有限集合逐渐填密区间,但任意有限一步仍缺少区间中的绝大多数点。要准确说明“接近整个区间”,需要度量集合之间的误差。
非空紧集与 Hausdorff 距离
设 是非空完备度量空间, 表示它的所有非空紧子集。对点 和非空集合 ,记 。两个非空紧集的 Hausdorff 距离定义为 第一项要求 的每一点都靠近 ;第二项反过来要求 的每一点都靠近 。紧性保证这些量有限。两项都为零时,由紧集的闭性可知两集合相等。对第三个非空紧集 ,选择 中离 最近的点,先得到 ;对 取上确界,再交换 重复一次,便得到三角不等式 。连同对称性与非负性,这证明它确实是 上的度量。
例如 、。因为 ,第一项为零;第二项在中点 达到 ,所以 。只检查第一项会把这个不同的集合误当作误差为零。
下面使用一个度量空间事实:当 完备时, 也完备。其作用是保证集合的 Cauchy 序列仍有非空紧极限。可以从紧性判别看出这一点:若 为 Hausdorff–Cauchy 序列,对任意 ,足够靠后的集合都在某个紧集 的 邻域内。用 的有限个半径 的球,再加上有限个前项的有限覆盖,就得到 的有限个半径 的球覆盖。于是该并集全有界,其闭包 在完备空间中紧。
在 中取 这是嵌套非空紧集的交,因而非空紧;它恰由序列 、 的极限点组成。若 时 ,固定 ,从后续每个 选离 不超过 的点,再在紧集 中取收敛子列,便得到 。反向对 的极限表示取界,得到 。因此 ,完备性成立。[1]
Hutchinson 算子的收缩性
给定有限个映射 ,其中 。假定每个映射满足统一的距离估计 并令 。这里的“严格压缩”指存在这样的全局常数;仅有每一对不同点的距离都严格减小,不足以给出本节使用的统一 。
定义 Hutchinson 算子 压缩映射连续,紧集的连续像仍紧,有限个非空紧集的并仍是非空紧集,所以 。选择紧集作为论域也避免了把一般闭集的连续像误当成闭集。
要证明这个算子收缩,取任意 ,写成 ,其中 。从 选离 最近的点 ;紧性保证最近点存在。由于 , 对所有 取上确界,再交换 重复论证,就得到 关键是给两集合中的点使用同一个分支 作比较;无需假设分支的像相互分离。[2]
唯一吸引子及确定性误差界
从任意 出发,令 ,并记 。反复应用收缩性, 对 ,沿相邻项使用三角不等式,把误差相加: 因为 ,这是 Cauchy 序列。由前述完备性,存在 使 。收缩性还给出 故 。若另有非空紧集 ,则 ,由 强迫距离为零,得到 。这完整证明了非空紧吸引子的存在性和唯一性。
令上面求和式中的 ,便得到可以停止计算的界 如果已知初始误差,还可用 ;但计算时通常不知道 ,所以由第一步距离得到的 更实用。给定 ,只需找到 的 。当 时,各映射都是常值映射,一步就达到吸引子;当 时,初始集合已经是不动集。
区间吸引子的可复算例子
回到 、。它们把 分别送到 、,所以 ;由唯一性,吸引子就是 。
从 出发,归纳得到 归纳步骤中,第一支把分子送到 ,第二支把分子送到 ,分母都变为 。所有分支的并因此恰好给出下一层。
集合 位于 内,相邻点间距为 ,最后一点是 。区间内部的相邻点之间,最远点到 的距离至多是间距的一半;右端点 到它的距离却为整个间距。因此 本例中 、,一般误差界恰好给出同一个数。若目标误差为 ,取 即可:得到32个点,最后一点为 。
一个变式是把初始集合改为 。此时 包含两个端点,最大误差出现在相邻点的中点,故 。第一步距离仍为 ,通用界仍是 ,因而这次上界并不紧。误差界可以保证精度,却不必等于实际误差。
有理仿射系统的精确实现
下面实现实数轴上的有限仿射系统 ,要求 、初始点和正容差均为有理数,且 。函数返回排序后的有限点集、误差上界 和迭代层数,不修改输入。它完整应用所有分支,采用 Fraction 精确算术;拒绝浮点输入,以免把近似的小数误作已经验证的误差证书。
from fractions import Fraction
def rational(value):
if isinstance(value, bool) or not isinstance(value, (int, Fraction)):
raise TypeError("use int or Fraction, not floating-point input")
return Fraction(value)
def deterministic_ifs(maps, seed, eps, *, max_candidates=100000,
max_iter=100):
for value, lower in ((max_candidates, 1), (max_iter, 0)):
if isinstance(value, bool) or not isinstance(value, int) or value < lower:
raise ValueError("invalid resource limit")
maps = tuple((rational(a), rational(b)) for a, b in maps)
if not maps:
raise ValueError("at least one map is required")
q = max(abs(a) for a, b in maps)
if q >= 1:
raise ValueError("every map must be a strict contraction")
points = tuple(sorted({rational(x) for x in seed}))
if not points:
raise ValueError("seed must be nonempty")
eps = rational(eps)
if eps <= 0:
raise ValueError("eps must be positive")
def image(values):
if len(maps) * len(values) > max_candidates:
raise MemoryError("candidate budget exceeded before expansion")
return tuple(sorted({a * x + b for a, b in maps for x in values}))
def hausdorff(left, right):
return max(max(min(abs(x - y) for y in right) for x in left),
max(min(abs(y - x) for x in left) for y in right))
first = image(points)
bound = hausdorff(points, first) / (1 - q)
n = 0
while bound > eps:
if n >= max_iter:
raise RuntimeError("iteration budget exhausted before tolerance")
points = first if n == 0 else image(points)
n += 1
bound *= q
return points, bound, n
maps = [(Fraction(1, 2), 0), (Fraction(1, 2), Fraction(1, 2))]
points, bound, n = deterministic_ifs(maps, [0], Fraction(1, 32))
print(n, len(points), points[0], points[-1], bound)
# 5 32 0 31/32 1/32
正确性由两个不变量连接到前面的证明:每次更新后的 points 精确等于 ;bound 精确等于 。去掉重复点只改变集合的表示,不改变集合。循环只在此界不超过容差时返回;若资源不足则明确报错,不把未达精度的点集作为成功结果。
设第 层去重后有 个点。一次展开生成 个候选,去重后有 个点;在把有理数运算和散列看作单位操作的模型中,集合生成预期需要 次操作,排序需要 次比较。代码首次朴素计算 Hausdorff 距离还需 次距离比较。两层集合和临时候选集合的存储为 个有理数。位复杂度还取决于分子、分母的长度,不能把任意大整数运算视为固定成本。
最坏情况下点数按 增长;较小误差不意味着计算便宜。max_candidates 在生成前按 保守检查,可能拒绝实际重复点很多的展开;max_iter 则限制迭代层数。两项限制均属于实现的资源预算,而非吸引子存在性的条件。
条件失效与数值边界
完备性确实用于保留极限。若 、,映射仍把 送入自身且压缩比为 ,但零不属于 。若存在非空紧不变集 ,它的最小值 应满足 ,矛盾。
压缩常数严格小于一也不能删去。在 上,恒等映射使每个非空紧集都不变,唯一性失效;平移 则没有非空紧不变集。有限性保证有限并仍紧;例如无限多个常值映射 虽然各自的压缩常数都是零,但其像的并为 ,不是闭集,算子已不能按上述定义把紧集送入紧集。无限系统需另加条件。唯一性也限于非空紧集:单映射 在 上的紧吸引子是 ,而非紧集 同样满足集合不变式。
若改用浮点数,每一步存储集合 与精确映射结果 之间会有额外误差。假定已经独立保证这项 Hausdorff 误差不超过 ,则 递推给出 因此反复迭代不会消除持续产生的舍入误差;当 接近一时,误差累积尤其明显。实际程序还可能发生溢出、产生 NaN,或将过近的点舍入为同一点。没有经过验证的 时,直接套用精确公式不能得到严格浮点误差证书。上面的实现通过精确有理数避免这一问题,包括拒绝 NaN、无穷和普通浮点参数;若要处理非有理映射,可改用有验证界的区间算法。
绘制随机迭代点时,每轮通常只选择一个分支,这与这里保留所有分支的集合迭代不同。一张有限随机点云即使外观接近吸引子,也没有自动给出“吸引子的每一点都靠近已绘点”的反向 Hausdorff 界。随机方法的概率性结论需要另设选枝机制并单独证明,不能用有限图像替代本篇的确定性覆盖估计。
参考资料
- ↑ John E. Hutchinson. Fractals and Self Similarity, Indiana University Mathematics Journal 30 (1981), 713–747。链接为作者重排版;§2.4,第6页讨论 Hausdorff 距离及完备性。
- ↑ Hutchinson,同上,作者重排版§3.1,第10—12页;§3.2,第12页的收缩定理。第13页的补注说明:若改在一般非空闭有界集上操作,需要对像取闭包;在本篇使用的非空紧集空间上无需该修正。