给定N,B和D:找到一组N个码字(1 <= N <= 64),每个长度为B位(1 <= B <= 8),使得每个码字至少是距离每个其他码字的D(1 <= D <= 7)的汉明距离。一对码字之间的汉明距离是二进制符号不同的二进制位数。考虑两个代码字0x554和0x234及其差异(0x554表示带有十六进制数字5,5和4的十六进制数字):
0x554 = 0101 0101 0100
0x234 = 0010 0011 0100
位差:xxx xx 由于五位不同,汉明距离为5。
实施例
input :- N=16 B=7 D=3
output :- 0 7 25 30 42 45 51 52 75 76 82 85 97 102 120 127
我可以生成长度为B的所有代码字(二进制字符串)并尝试挑选大小为N的每个子集,并查看所选子集中的每个数字与子集中的其他数字是否至少相距D汉明距离但这将需要时间nCk
(2**B) C N
在最坏的情况下可能会很糟糕。 如何有效地生成数字?
答案 0 :(得分:1)
This是一个类似的问题,答案/评论提到有效的构造是一个悬而未决的问题!
这是紧凑方法,使用整数编程( NP-hard ),在python3中使用cvxpy建模:
import itertools
import operator
from cvxpy import *
N = 16
B = 7
D = 3
# Vars.
X = Bool(N, B)
Y = Bool(len(list(itertools.combinations(range(N), 2))), B) # ugly -> could use bin-formula
# Objective
objective = Minimize(1) # dummy objective -> only feasibility needed!
# Constraints
def xor_vectors(a, b, y):
""" Linearization of y-vec = xor(a-vec, b-vec) """
return [y <= a + b,
y >= a-b,
y >= b-a,
y <= 2-a-b]
constraints_xor = reduce(operator.add, [xor_vectors(X[pair[0], :], X[pair[1], :], Y[ind, :]) for ind, pair in
enumerate(itertools.combinations(range(N), 2))])
constraints_hamming_dist = [sum_entries(Y, axis=1) >= D]
# Build problem
prob = Problem(objective, constraints_xor + constraints_hamming_dist)
# Solve
result = prob.solve(solver=GUROBI, MIPFocus=1, verbose=True)
print(X.value)
输出:
.... (verbose output)
111 108 0.00000 18 424 - 0.00000 - 511 5s
* 264 13 37 0.0000000 0.00000 0.00% 500 7s
Cutting planes:
Gomory: 2
Zero half: 26
Explored 270 nodes (139404 simplex iterations) in 7.74 seconds
Thread count was 4 (of 4 available processors)
Optimal solution found (tolerance 1.00e-04)
Best objective 0.000000000000e+00, best bound 0.000000000000e+00, gap 0.0%
[[ 1. 1. 1. 1. 1. 1. 1.]
[ 1. 0. 1. 0. 1. 1. 0.]
[ 1. 1. 1. 0. 0. 0. 1.]
[ 1. 1. 0. 0. 1. 0. 0.]
[ 0. 1. 1. 1. 1. 0. 0.]
[ 0. 1. 0. 0. 1. 1. 1.]
[ 0. 1. 1. 0. 0. 1. 0.]
[ 0. 1. 0. 1. 0. 0. 1.]
[ 1. 1. 0. 1. 0. 1. 0.]
[ 1. 0. 1. 1. 0. 0. 0.]
[ 0. 0. 0. 1. 1. 1. 0.]
[ 0. 0. 1. 1. 0. 1. 1.]
[ 0. 0. 0. 0. 0. 0. 0.]
[ 1. 0. 0. 0. 0. 1. 1.]
[ 1. 0. 0. 1. 1. 0. 1.]
[ 0. 0. 1. 0. 1. 0. 1.]]
编辑:早期的方法(不同的求解器 - 参数)需要48分钟,现在只需 ~8秒。我使用了商业解决方案(非学术用途免费)!
我认为SAT解决方法可能会更快,但似乎确实这是一个非常难的问题(如我上面的链接所述)!