4. 混杂别名结构的代数表达
在二水平部分因子设计中,每一个因子只有“低水平”和“高水平”两种状态。为了把混杂结构变成可以推导、可以编程计算的对象,我们通常把低水平编码为 0、高水平编码为 1,或者采用 ±1 编码。本节采用 0/1 编码,并约定:因子的幂次只取 0 或 1,任何幂次按模 2 化简,即 x² = x、x⁰ = 1。这一约定是后续所有代数运算的基础,务必先固定下来,全文与图示保持一致。
在这个约定下,一个设计中的任意效应都可以写成一个“字”(word),即若干因子的一次幂之积。例如 A、B、C 三个因子,主效应 A 对应多项式 x_A,交互效应 AB 对应 x_A·x_B,三阶交互 ABC 对应 x_A·x_B·x_C。所谓“混杂别名结构”,就是问:在这个设计里,哪两个(或更多)效应在数据上无法区分?代数上,这等价于问:它们的字相乘后,是否等于设计定义关系(defining relation)中的某个字。
一、从生成元到定义关系:模2乘法的核心操作
考虑一个 2^(3-1) 设计,即三个因子、只做 4 次试验的一半实施。设生成元为 C = AB,用 0/1 编码写成多项式关系:x_C = x_A·x_B。把等式两边同乘 x_C(因为 x_C² = x_C,模 2 下幂次化简),得到:
x_A·x_B·x_C = x_C·x_C = x_C² = x_C
更规范的做法是把生成关系写成“等于单位元 I”的形式。定义 I 为全 1 列(对应多项式 1)。由 C = AB 两边同乘 C,得 I = ABC。这里的 ABC 就是该设计的定义关系字,记作 I = ABC。它说明:在这个设计中,三阶交互 ABC 与总体均值(单位元)完全混杂,因此 ABC 无法被估计。
有了定义关系,任何效应的别名都可以通过“该效应字 × 定义关系字”得到。例如求 A 的别名:
A × (ABC) = A·A·B·C = (A²)·B·C = A·B·C = ABC
因为 A² 按模 2 化简为 A(在 0/1 编码下 A² = A),所以 A 与 BC 互为别名。同理 B 与 AC 别名,C 与 AB 别名。这正是我们熟悉的 2^(3-1) 分辨率 III 设计的混杂结构:主效应两两与二阶交互混杂。
二、用多项式表示多个生成元的情形
当设计有多个生成元时,定义关系不止一个,而是由所有生成元字及其两两、三三……的模 2 乘积共同构成一个“定义关系组”。以 2^(5-2) 设计为例,设生成元为 D = AB、E = AC。先写出两个基本关系:I = ABD、I = ACE。再把它们相乘:
(ABD)(ACE) = A·A·B·C·D·E = A·B·C·D·E = ABCDE
于是定义关系组为 {I, ABD, ACE, ABCDE}。注意 A·A = A² = A,所以乘积中 A 只保留一次。这个关系组是封闭的:任意两个关系字相乘,结果仍在组内。它构成了判断别名的“完整字典”。
求某个效应的全部别名时,只需把它与关系组中每个非 I 的字逐一相乘。例如求 D 的别名:D×ABD = AB(因 D² = D),D×ACE = ACDE,D×ABCDE = ABCE。所以 D 的别名集合是 {AB, ACDE, ABCE}。这意味着在这个设计里,主效应 D 与二阶交互 AB、四阶交互 ACDE、四阶交互 ABCE 全部混杂,无法单独估计。
三、把别名结构写成可计算的算法
手工推导容易出错,尤其是因子数较多时。由于模 2 运算与二进制异或(XOR)天然对应,我们可以把每个字表示成一个位向量:第 i 位为 1 表示该字包含第 i 个因子。于是“两字相乘”就变成“两个位向量按位异或”,因为相同因子出现两次会抵消(A·A = A² = A,在 0/1 编码下等价于该因子只保留一次,位运算中表现为 1 XOR 1 = 0 的抵消语义需按编码约定处理)。更稳妥的做法是:用集合的对称差实现乘法,即两字相乘 = 两因子集合的对称差。下面给出一个可直接运行的 Python 示例,用于生成定义关系组并求任意效应的别名集合:
from itertools import combinations
def word_mul(w1, w2):
# 字用 frozenset 表示因子集合;模2乘法 = 对称差
return frozenset(w1) ^ frozenset(w2)
def defining_group(generators):
# generators: 生成元字列表,如 [{'A','B','D'}, {'A','C','E'}]
group = {frozenset()} # 单位元 I
frontier = [frozenset(g) for g in generators]
while frontier:
w = frontier.pop()
if w in group:
continue
group.add(w)
for g in generators:
nxt = word_mul(w, frozenset(g))
if nxt not in group:
frontier.append(nxt)
return group
def aliases(effect, group):
e = frozenset(effect)
return sorted(''.join(sorted(word_mul(e, g))) for g in group if g)
gens = [{'A','B','D'}, {'A','C','E'}]
G = defining_group(gens)
print("定义关系组:", sorted(''.join(sorted(w)) or 'I' for w in G))
print("D 的别名:", aliases({'D'}, G))
运行这段代码(示例输出,非实测):定义关系组为 ['I', 'ABD', 'ACE', 'ABCDE'],D 的别名为 ['AB', 'ABCE', 'ACDE'],与手工推导完全一致。这种“集合对称差”的实现方式把代数运算变成了可复用的程序,便于在因子数较多、生成元较复杂时批量检查混杂结构。
四、用别名结构反推设计的分辨率与可用性
得到别名集合后,一个重要的判读动作是看“最短别名长度”。若某主效应的别名中包含二阶交互,说明主效应与二阶交互混杂,该设计的分辨率至多为 III,主效应估计会受到二阶交互污染,通常只适合筛选试验。若所有主效应的别名最短为三阶交互,则分辨率为 IV,主效应可干净估计,但二阶交互之间可能互相混杂。上例中 D 的别名含 AB(二阶),故该 2^(5-2) 设计为分辨率 III,主效应不可靠,需要谨慎解释。
| 效应字 | 与关系组相乘 | 别名伙伴 | 最短别名阶数 |
|---|---|---|---|
| A | A×ABD, A×ACE, A×ABCDE | BD, CE, BCDE | 2(与 BD、CE 混杂) |
| D | D×ABD, D×ACE, D×ABCDE | AB, ACDE, ABCE | 2(与 AB 混杂) |
| AB | AB×ABD, AB×ACE, AB×ABCDE | D, BCE, CDE | 1(与主效应 D 混杂) |
表中 AB 与 D 互为别名,进一步印证了分辨率 III 的判断:二阶交互 AB 与主效应 D 无法区分。实际分析时,如果 D 显著,我们不能直接断言是 D 起作用,也可能是 AB 在起作用,必须结合工程知识或追加试验来区分。
五、代数表达的工程价值
把混杂结构写成模 2 多项式与定义关系组,最大的价值在于“可计算、可核查、可复用”。设计生成元一旦确定,定义关系组和全部别名集合就可以由程序自动生成,避免人工推导遗漏;在试验方案评审阶段,可以直接检查是否存在“主效应与二阶交互混杂”这类高风险别名;在数据分析阶段,也能明确哪些项可以进入模型、哪些项必须合并或舍弃。建议在每次使用部分因子设计前,先用上述算法输出完整的别名表,再结合分辨率要求决定是否调整生成元或增加试验次数。
需要强调的是,模 2 运算的化简规则(A² = A)与 0/1 编码约定必须前后一致。若改用 ±1 编码,则 A² = 1,乘法规则变为符号相乘,别名推导的中间形式会不同,但最终的混杂结论应当一致。实际教学中建议固定一种编码贯穿始终,避免在推导过程中混用导致符号错误。