ОБНОВЛЕННЫЙ ОТВЕТ
Глядя на пример вывода кода Уолтера Тросса, я думаю, что генерация случайного решения может быть упрощена до следующего:
Возьмем любой вектор для начала, например, для n= 8, m = 3, k = 5:
A: 01001100
После каждого шага суммируйте векторы, чтобы узнать, сколько раз использовалась каждая позиция:
SUM: 01001100
Затем,для следующего вектора поместите те в позиции, которые использовались меньше всего (в данном случае ноль раз), например:
B: 00110001
, чтобы получить:
A: 01001100
B: 00110001
SUM: 01111101
Тогда естьОсталось 2 наименее используемых позиции, поэтому для 3 позиций в следующем векторе используйте эти 2 позиции, а затем поместите третью в любом месте:
C: 10010010
, чтобы получить:
A: 01001100
B: 00110001
C: 10010010
SUM: 11121111 (or reset to 00010000 at this point)
Затем для следующего вектора у вас есть 7 наименее используемых позиций (те, которые в сумме), поэтому выберите любые 3, например:
D: 10100010
, чтобы получить:
A: 01001100
B: 00110001
C: 10010010
D: 10100010
SUM: 21221121
И в качестве конечного вектора выберите любую из 4 наименее используемых позиций, например:
E: 01000101
Чтобы сгенерировать все решения, просто сгенерируйте всеy возможный вектор на каждом шаге:
A: 11100000, 11010000, 11001000, ... 00000111
Затем, например, когда A и SUM равны 11100000:
B: 00011100, 00011010, 00011001, ... 00000111
Затем, например, когда B равно 00011100 и SUM равно 11111100:
C: 10000011, 01000011, 00100011, 00010011, 00001011, 00000111
Затем, например, когда C равно 10000011, а SUM равно 21111111:
D: 01110000, 01101000, 01100100, ... 00000111
И, наконец, например, когда D равно 01110000 и SUM равно 22221111:
E: 00001110, 00001101, 00001011, 00000111
Этоприведет к C (8,3) × C (5,3) × C (8,1) × C (7,3) × C (4,3) = 56 × 10 × 8 × 35 × 4 = 627 200 решенийдля n = 8, m = 3, k = 5.
На самом деле, вам нужно добавить метод, чтобы не повторять один и тот же вектор и не рисовать себя в углу;так что я не думаю, что это будет проще, чем ответ Уолтера.
ПЕРВОНАЧАЛЬНЫЙ ОТВЕТ - ОСНОВНЫЕ ВОПРОСЫ
(я предполагаю, что m не больше n / 2, т. Е. Число единиц не больше, чем числонулей. В противном случае используйте симметричный подход.)
Когда k × m не больше n, очевидно, есть оптимальные решения, например:
n=10, m=3, k=3:
A: 1110000000
B: 0001110000
C: 0000001110
, где расстояния Хэммингавсе равны 2 × m:
|AB|=6, |AC|=6, |BC|=6, total=18
Когда k × m больше n, решения, в которых разница в расстояниях Хэмминга между последовательными векторами минимизирована, предлагают наибольшее общее расстояние:
n=8, m=3, k=4:
A: 11100000
B: 00111000
C: 00001110
D: 10000011
|AB|=4, |AC|=6, |AD|=4, |BC|=4, |BD|=6, |CD|=4, total=28
n=8, m=3, k=4:
A: 11100000
B: 00011100
C: 00001110
D: 00000111
|AB|=6, |AC|=6, |AD|=6, |BC|=2, |BD|=4, |CD|=2, total=26
Итак, практически, вы берете m × k и смотрите, насколько оно больше, чем n, назовем его x = m × k − n, а это x - число перекрытий, т. Е. Как часто будет вектородин в той же позиции, что и предыдущий вектор.Затем вы распределяете перекрытие между различными векторами как можно более равномерно, чтобы максимизировать общее расстояние.
В приведенном выше примере x = 3 × 4−8 = 4, и у нас есть 4 вектора, поэтому мы можем равномерно распределить перекрытие, и каждый вектор имеет 1 в том же положении, что и предыдущий вектор.
Чтобы сгенерировать все уникальные решения, вы можете:
- Рассчитать x = m × k − n и сгенерировать все разбиения x на k частей с наименьшим возможным максимумом.значение:
n=8, m=3, k=5 -> x=7
22111, 21211, 21121, 21112, 12211, 12121, 12112, 11221, 11212, 11122
(discard partitions with value 3)
- Генерировать все векторы, которые будут использоваться в качестве вектора A, например:
A: 11100000, 11010000, 11001000, 11000100, ... 00000111
- Для каждого из них сгенерироватьвсе векторы B, которые лексикографически меньше, чем вектор A, и имеют правильное количество перекрывающихся векторов A (в примере 1 и 2), например:
A: 10100100
overlap=1:
B: 10011000, 10010010, 10010001, 10001010, 10001001, 10000011, 01110000, ... 00000111
overlap=2:
B: 10100010, 10100001, 10010100, 10001100, 10000110, 10000101, 01100100, ... 00100101
- Для каждого из них генерируйте все векторы C и так далее, пока у вас не будет наборов из k векторов.При генерации последнего вектора необходимо учитывать перекрытие с предыдущим, а также со следующим (т.е. первым) вектором.
Я предполагаю, что лучше всего рассматривать разбиения x на k как двоичное дерево:
1 2
11 12 21 22
111 112 121 122 211 212 221
1112 1121 1122 1211 1212 1221 2111 2112 2121 2211
11122 11212 11221 12112 12121 12211 21112 21121 21211 22111
и обходить это дерево при создании решений, чтобы каждый векторнужно генерировать только один раз.
Я думаю, что этот метод работает только для некоторых значений n, m и k; Я не уверен, что это можно сделать для общего случая.