在矩形整数矩阵中识别互为标量倍数的行向量
解决方案
核心思路为针对整数矩阵特性,采用无浮点运算的整数归一化方法,完全规避浮点误差,同时天然支持正负标量倍数的匹配。
步骤1:对每行做标准化归一化
- 单独处理全零行(全零行是任意行的0倍,可根据需求单独过滤)
- 计算当前行所有非零元素绝对值的最大公约数(GCD)
- 用行内所有元素除以该GCD,得到公约数为±1的最简整数行
- 统一符号规则:将最简行的第一个非零元素调整为正数,若第一个非零元素为负,则整行乘以-1
经过上述处理后,所有互为标量倍数的行都会得到完全相同的归一化结果,比如示例中的第0行[-1,-1,0,0]归一化后为[1,1,0,0],倒数第3行[1,1,0,0]归一化后结果完全一致,可直接匹配。
步骤2:分组匹配符合要求的行
将所有行按照归一化结果分组,同一组内的行天然互为标量倍数。若需额外排除「可表示为多个其他行线性组合」的行,只需对所有唯一归一化行组成的矩阵做高斯消元得到线性无关基,不在基中的归一化行即可被过滤,剩余组内的行均仅为组内其他行的标量倍数。
代码实现示例
import numpy as np from math import gcd from functools import reduce from collections import defaultdict def normalize_row(row): # 处理全零行 if np.all(row == 0): return tuple(np.zeros_like(row)) # 计算所有非零元素绝对值的GCD non_zero = row[row != 0] g = reduce(gcd, np.abs(non_zero)) # 除以GCD得到最简行 norm_row = row // g # 取第一个非零元素的符号,统一调整为正 first_non_zero_idx = np.argmax(norm_row != 0) sign = norm_row[first_non_zero_idx] if sign < 0: norm_row = -norm_row return tuple(norm_row) # 示例矩阵 A = np.array([[-1, -1, 0, 0], [-1, -1, 0, 1], [-1, 0, -1, 0], [-1, 0, 0, 0], [-1, 0, 0, 1], [-1, 0, 1, 1], [-1, 1, -1, 0], [-1, 1, 0, 0], [-1, 1, 1, 0], [ 0, -1, 0, 0], [ 0, -1, 0, 1], [ 0, -1, 1, 0], [ 0, -1, 1, 1], [ 0, 0, -1, 0], [ 0, 0, 0, 1], [ 0, 0, 1, 0], [ 0, 1, -1, 0], [ 0, 1, 0, 0], [ 0, 1, 0, 1], [ 0, 1, 1, 0], [ 0, 1, 1, 1], [ 1, -1, 0, 0], [ 1, -1, 1, 0], [ 1, 0, 0, 0], [ 1, 0, 0, 1], [ 1, 0, 1, 0], [ 1, 0, 1, 1], [ 1, 1, 0, 0], [ 1, 1, 0, 1], [ 1, 1, 1, 0]]) # 按归一化结果分组 groups = defaultdict(list) for idx, row in enumerate(A): norm = normalize_row(row) groups[norm].append(idx) # 输出互为标量倍数的行组 for norm, row_indices in groups.items(): if len(row_indices) >= 2: print(f"归一化结果为{norm}的行索引:{row_indices}")
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

