外代数算法
最近正好在思考如何用代数算法来进行去重, 突然意识到今年集训队论文有一篇就综述的这个东西, 而且外代数这个视角已经有人指出过了. 那么, 让我们来看看如何解释...
注: 以下带有 😎 的章节被判定为适合 OI 选手阅读.
从简单路径开始 😎
给定一张图, 如何判定它是否有一条长为 \(k\) 的简单路径?
显然, 这个问题是 NPC 的, 因为 \(k=n\) 的情况是众所周知困难的 Hamilton 路问题. 但当 \(k\) 非常小的时候, 我们还是希望能有一个相对快速的算法.
如果运行随机化的话, 我们有可能想到这样一种做法:
- 给每个点随机赋予一个 \(1\sim k\) 之间的颜色, 然后做状压 DP, 维护一条经过的点没有重复颜色的路径.
显然, 这个算法单次的运行时间是 \(\tilde O(2^k n)\), 但我们也得分析一下它的正确率. 一条长为 \(k\) 的路径有 \(k!\) 种染色是支持颜色互不相同的, 但我们的染色方案中有 \(k^k\) 种情况, 所以概率是 \(k!/k^k \geq e^{-k}\). 所以, 为了保证有常数的概率跑出解, 需要运行 \(e^k\) 轮, 所以我们实际上复杂度应该是 \(\tilde O((2e)^k n)\).
注: 历史上这个做法首先由 Alon, Yuster 和 Zwick 与 1994 年提出.
值得一提的是, 这种做法也正好可以解决反过来的一类问题: 给定一个每个节点都被染色的图, 如何找一个最小的连通块, 包含至少 \(k\) 种颜色? 我们还是可以把每个颜色都随机映射到 \(k\) 个之中的一种, 然后跑 Steiner 树就好了. 这种题似乎早就在 OI 里出现过了, 例如 THUSCH 2017 巧克力, 考虑到 2014 年就有人总结过, 应该有远远更早出现的题.
外代数的出现 😎
我们知道一个经典的判断二分图匹配的代数算法: 对图的邻接矩阵中每条边赋予一个单独的变量, 图的匹配存在当且仅当 \(\det A\) 作为多项式非零. 那么 Schwartz–Zippel 引理告诉我们, 只要每个变量赋予一个随机数, 就可以以 \(\geq 1-n/|\mathbb F|\) 的概率得到正确的答案.
那么我们的想法就是, 能否设计一个代数结构 \(A\), 然后直接利用这个代数结构做数数
使得它能统计点不重复的路径方案, 而且我们可以通过随机带入值的方法来快速判断它非零呢?
直观上看, 我们希望设计一个代数结构, 其中有一些元素满足 \(x^2 = 0\), 这样就可以作为点权了.
另一个思考角度是, 原来的随机化做法是把每个点随机映射到了 \(k\) 个颜色中的一种, 我们考虑改换这个空间. 如果有一个 \(k\) 维线性空间, 我们把每个点随机映射到其中一个向量的话, 我们希望找的就是一个长为 \(k\) 的路径, 其上的点所包含的向量线性无关.
给定域 \(\mathbb F\) 上的线性空间 \(V\), 其上的外代数 (exterior algebra) \(\bigwedge V\) 是这样一个东西, 我们来不严谨地进行一下解释: 它就像多项式一样,
其中一个元素写成一些 \(v_1 \wedge v_2 \wedge \cdots \wedge v_k\) 的线性组合 (每项的 \(k\) 可以是不一样的, \(k\) 就是这个单项式的次数). 对每一项都是线性的, 也就是有 \((u + cv)\wedge w = (u\wedge w) + c(v\wedge w)\).
但只有这些信息是不够的, 这样定义出来的叫做张量代数, 而且我们的目的就是让 "\(x^2=0\)", 所以我们还需要加上一个条件:
- 对任意 \(v\in V\), \(v\wedge v = 0\).
这个条件有一个很直接的后果, 就是 \(x\wedge y = -y\wedge x\), 因为 \((x+y)\wedge(x+y) - x\wedge x - y\wedge y = 0\).
这样一来, 容易验证, 如果 \(v_1\wedge \cdots \wedge v_n\) 中有两个相同的向量, 那么它就等于 \(0\). 基于这一点, 在有限维线性空间上, 有一个便于计算的刻画方法.
记 \(k\) 阶外代数 \(\bigwedge^k (V)\) 是所有次数为 \(k\) 的项的线性组合构成的线性空间, 我们考虑 \(V\) 的一组基 \(e_1,\dots, e_n\), 那么对于任何一个 \(k\) 元子集 \(\{a_1,\dots,a_k\}\), \(\bigwedge^k (V)\) 的一组基就是全体 \(k\) 元子集给出的 \(e_{a_1}\wedge \cdots \wedge e_{a_k}\).
这样一来, 我们可以将任何一个 \(f \in \bigwedge V\) 唯一地用一系列数 \(f_S\) 来存储, 计算 \(f \land g\) 的时候, 考虑 \(f_S\) 和 \(g_T\) 的贡献. 如果 \(S\) 和 \(T\) 有交, 那么它们的乘积项其实就是 \(0\), 否则贡献给 \(S\sqcup T\) 项, 同时乘以 "\(S, T\) 之间的逆序对数的 \(-1\) 次方".
值得一提的是, 注意 \(n\) 个 \(\bigwedge^1(V)\) 乘起来的时候, 我们得到的是 \(v_1 \wedge v_2 \wedge \cdots \wedge v_n = \det(v_1 | v_2 | \cdots | v_n) (e_1 \wedge \cdots \wedge e_n)\), 其中行列式按照选取的基计算.
简单路径问题的解法 😎
现在固定一个 \(k\) 维线性空间, 对每个节点 \(i\), 我们随机赋予一个向量 \(v_i\). 那么考虑维护
显然它是可以 DP 维护的, 而外代数的信息量有 \(2^k\) 大小, 我们计算的时间是 \(\tilde O(2^k n)\).
增加 \(w\) 的部分是为了相同点集对应的不同边集, 这个式子的答案本质上是个 \(2k-1\) 次的多项式, 所以 Schwartz–Zippel 引理告诉我们它非零的概率 \(\geq 1-(2k-1)/|\mathbb F|\).
这个想法的雏形最开始由 Williams 在 2009 年提出.
注意这个做法和前面的随机染色相比, 好处是底数更小了, 但相应的也有一个后果, 就是不太容易做带权的版本.
这个外代数方法也被一些人称为 外张量 (extensor).
去随机化
首先我们可以将外代数的部分通过 Vandermonde 编码 的方式进行去随机化. 对于 \(\alpha \in \mathbb F\), 定义
根据 Vandermonde 行列式的熟知结果, 我们知道当 \(\alpha_i\) 互不相同的, 不超过 \(k\) 个的时候, \(\bigwedge_i v_{\alpha_i}\) 也是非零的. 这意味着我们只需要随机 \(w\) 的部分, 把正确率提高到 \(\geq 1-(k-1)/|\mathbb F|\).
好吧这个提高显然没有人关心, 但下一步我们可以得到一个真的完全确定性的算法.
我们现在仍然不能丢弃 \(w\) 的原因在于, 不同的答案可能正负相抵. 但如果考虑把向量复制两份呢? 考虑
现在把 \(k\) 个不同的 \(v_\alpha'\) 乘起来, 得到的就是 \((-1)^{f(k)} \cdot \det(v_{\alpha_1}|\cdots|v_{\alpha_k})^2\) 了, 也就是说, 无论如何排布, 行列式都是同号的, 不可能抵消成 \(0\), 我们可以不在有限域上算这个结果, 而是在 \(\mathbb Z\) 上计算, 把 \(\alpha\) 取 \(1\sim n\) 的整数.
现在答案的位数是 \(\operatorname{poly}(n)\) 的, 但我们多用了一倍的维数, 总之我们做到了 \(O(4^k \operatorname{poly}(n))\) 的时间的确定性算法.
这个做法由 Branda, Dell 和 Husfeldt 在 2018 年提出. 但值得一提的是, 确定性做法已经有更快的 \(O(2.5961^k \operatorname{poly}(n))\) 了.
近似计数
前面的方法中我们将 \(v_\alpha\) 特化为了 Vandermonde 向量, 如果每个向量现在改成 \(\{-1, 1\}^k\) 中随机的话, 行列式的结果可以帮助我们得到一个图的 \(k\)-简单路径数的估计.
设 \(B\) 是一个每个元素都在 \(-1, 1\) 里随机的矩阵, 可以证明 \(\mathbb E[\det B^2] = k!\), 经过进一步的分析, 可以证明为了得到路径数的 \(\epsilon\) 近似, 只需要 \(O(\epsilon^{-2})\) 次采样. 所以我们有了一个 \(\tilde O(\epsilon^{-2} 4^k n)\) 复杂度的近似算法.
可能的其他应用 😎
回忆如何判定二分图是否存在匹配, 我们可以扩展到如下问题:
- 有图 \(G = L \sqcup R\), 问是否存在 \(L\) 内部的一条简单路径, 同时这个简单路径的点集到 \(R\) 有完美匹配, 其中 \(|R| = k\).
我们将每个点可以匹配的点对应的分量赋予一个随机数, 这样再跑之前提到的 DP, 就能计算答案了. 复杂度仍然是 \(\tilde O(2^k n)\).
总的来说, 我们可以处理某种这样的问题: 从一个大集合 \(U\) 里选出一个有某些规则的子集 (这个规则可以 DP 出来), 同时这个子集又必须在一个线性拟阵里, 问这个子集能否大小达到 \(k\). 我们只需要将线性拟阵随机投影到 \(k\) 维空间上, 然后做 DP 就行了.
3-匹配问题
回忆 \(3\)-匹配问题是一个三部图 \(V=V_1\sqcup V_2\sqcup V_3\), 其中每条边是一个 \(3\)-边, 意为 \(e\) 交每个 \(V_i\) 于一个点. 问是否存在一个完美匹配, 或者说选出 \(n\) 个三角形覆盖这 \(3n\) 个点.
回顾 \(2\)-匹配是有多项式复杂度算法的, 而且有代数算法, 就是求个行列式就行了.
现在我们考虑把 \(V_1, V_2\) 挂在矩阵上, \(M_{ij}\) 是一个外张量, 形如
那么 \(\det M\) 非零当且仅当有完美匹配.
但这里有个小问题, 外张量计算不是交换的, 所以我们还是要取特征为 \(2\) 的域, 这样变成了集合幂级数, 就容易计算了.
复杂度 \(\tilde O(2^n)\). 容易扩展为 \(k\times n\) 的 \(k\)-超图的匹配情况, 复杂度为 \(\tilde O(2^{(k-2)n})\).
这个做法首先由 Björklund 在 2010 年提出.
无向二分图上的 \(k\)-简单路
如果 \(G = L\sqcup R\), 并且只有 \(L, R\) 之间有无向边的话, 可以做到 \(\tilde O(2^{k/2} n^{O(1)})\) 判定是否有 \(k\)-简单路.
不妨考虑 \(k = 2\ell + 1\) 的情况, 从 \(L\) 出发. 现在对每个 \(R\) 部的点随机一个 \(\ell\) 维空间中的向量 \(v_i\), 在 \(L\) 部的转移的时候, 从 \(u_i\) 到 \(v_i\) 再到 \(u_{i+1}\) 的时候, 我们记一下 \(u_{i}\) 保证 \(u_{i-1}\neq u_{i+1}\).
这样求出来的是啥呢? 我们求出来的是
现在 \(R\) 侧的点一定是不重复的, 但 \(L\) 侧的点有可能重复.
注意我们的枚举路径保证了 \(u_1,\dots,u_{\ell+1}\) 没有相邻的重复点. 我们希望让总的来说出现重复的方案被抵消掉. 考虑让 \(\mathbb F\) 的特征为 \(2\), 那么对于最早出现的一对重复 \(u_i = u_j\), 我们将 \(u_i \leadsto u_j\) 这段路径翻转过来, 这就制造了有重复点的路径之间的一个对合, 对合的两条路径权值相同, 在特征为 \(2\) 的代数上抵消了.
这个做法首先由 Björklund, Husfeldt, Kaski 和 Koivisto 在 2010 年提出.
无向图上的 \(k\)-简单路
考虑将 \(G\) 分成两部 \(L\sqcup R\), 考虑如何判断是否有 \(k\)-简单路.
- 对于 \(R\) 内部的点, 我们每个点分配一个向量 \(v_i\).
- 对于 \(L\) 到 \(L\) 的边, 我们每条边分配一个向量 \(v'_i\).
- 在转移的时候, 如果从 \(L\) 到 \(R\) 到 \(L\), 我们要求这两个 \(L\) 点不同.
这样一来, 没有被外代数排除的路径具有如下性质:
- 经过 \(R\) 的点没有重复.
- 在 \(L\) 到 \(L\) 的边没有重复.
那么如果这样一条路径有重复经过的点, 取最早出现的一对位置 \(u_i, u_j\), 一定有 \(u_i, u_j \in L\), 考虑将其翻转, 我们证明这得到的是一条不同的路径:
- 如果路径中间经过了至少一个 \(R\) 点, 要么 \(R\) 不在正中间, 那么翻转后一定是不同的路径. 要么 \(R\) 在正中间, 那么这个 \(R\) 前后两个点一定是不同的.
- 如果路径中间经过的全都是 \(L\) 点, 那么因为它们的边不重复, 这条路径反转之后也一定与自身不同.
所以有重复的路径一定可以通过利用 \(\mathbb F_2\) 来抵消贡献.
接下来我们看看这个做法巧妙的地方, 它是如何节省线性空间的维数的呢? 我们选取概率 \(p\) 将一个点分给 \(L\), \(1-p\) 分给 \(R\), 那么如果一条长为 \(k\) 的路径存在, 那么它上面期望有 \((1-p)k\) 个 \(R\), 以及 \(p^2(k-1)\) 个 \(L\) 到 \(L\) 的边. 取 \(p = 1/2\) 的时候达到最优, 有总共需要的维数 \(\leq 3k/4\). 那么分配 \(3k/4+1\) 个维数, 根据 Markov 不等式, 我们有 \(\Omega(1/k)\) 的概率命中一组解, 重复采样就能以 \(\tilde O(2^{3k/4} n^{O(1)})\) 的时间判定了.
上面的做法实际上还可以继续挤一挤水, 注意 \(2^{3/4}\approx 1.68\), 经过一定仔细的计算, 会发现 \(|R| \leq k/2\) 且 \(L\) 到 \(L\) 经过的边数 \(\leq 0.207k\) 的时候, 解被命中的概率是某个 \(\Omega(c^k)\) 的, 这个 \(c\) 满足 \(2^{0.5 + 0.207} / c \approx 1.66\), 所以分别 \(0.707k + O(1)\) 个维数, 重复实验 \(O(c^{-k})\) 次, 就能以 \(\tilde O(1.66^k n^{O(1)})\) 的时间判定了.
这就得到了如下的结果:
(Björklund, 2009) 无向图的哈密顿路可以在 \(\tilde O(1.66^n)\) 时间内判定.
计算
在很多应用中, 我们只关心 \(\bigwedge V\) 乘以 \(V\) 中一个元素的复杂度, 显然这是可以做到 \(O(k 2^k)\) 的.
但 \(\bigwedge V\) 上一般的乘法能做到什么复杂度呢? 如果 \(\mathbb F\) 的特征是 \(2\), 这也是容易的, 因为 \(x \wedge y = y\wedge x\), 这个时候不需要考虑负号, 我们只需要做子集卷积就好了, 复杂度是 \(O(k^2 2^k)\).
对于一般的域来说就比较麻烦了. 首先考虑 \(x\land x = 0\) 这个现象, 这也是子集卷积面临的问题. 如果类比子集卷积的方法, 我们需要对不同次数的外张量分别计算, 这样的话计算的时候可以对规则做稍微的修改, 容许一些次数发生变化的计算, 并且最后提取出正确的信息.
考虑将规则修改为 \(e_i^2 = 1\), \(e_ie_j = -e_je_i\), 在 \(\mathbb C\) 上这定义出来的是 Clliford 代数 \(\mathrm{Cl}_k(\mathbb C)\), 对于 Clliford 代数的分类指出, 有代数同构 \(\mathrm{Cl}_{2p}(\mathbb C) \cong M_{2^p \times 2^p}(\mathbb C)\).
这是一个类似于有限群 DFT 的问题, Włodarczyk 在 2017 年给出了这个同构具体的 \(\tilde O(2^k)\) 的 (双向) 计算方法, 所以 Clliford 代数的乘法计算本质上等价于计算矩阵乘法. 通过这个思路, 目前做法只能做到 \(O(2^{\omega k/2})\), 暂时不知道是否有其他途径.