生成N个数,使得每个数之间的汉明距离至少为D.

时间:2016-06-23 18:56:22

标签: algorithm data-structures depth-first-search backtracking hamming-distance

给定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

在最坏的情况下可能会很糟糕。 如何有效地生成数字?

1 个答案:

答案 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解决方法可能会更快,但似乎确实这是一个非常难的问题(如我上面的链接所述)!