Подтвердить что ты не робот

Определить, является ли какая-либо перестановка строк в матрице Toeplitz

A Toeplitz matrix "- это матрица, в которой каждая нисходящая диагональ слева направо постоянна." Учитывая двоичную матрицу M, существует ли эффективный алгоритм, чтобы определить, есть ли перестановка строк, которые делают его Toeplitz?

Например, установите

M= [0 1 1]
   [1 1 0]
   [1 0 1]

Если вы меняете первый и второй строки, вы получаете

[1 1 0]
[0 1 1]
[1 0 1]

который является теплицем.

В python вы можете сделать случайную двоичную матрицу следующим образом.

n = 10
h = 10
M =  np.random.randint(2, size=(h,n))

Я хотел бы применить тест к M.

(Обратите внимание, что матрица M не должна быть квадратной.)

4b9b3361

Ответ 1

Эта проблема может быть решена в линейном O (h * w) времени, где h - количество строк, а w - количество столбцов.

Построить граф, где каждая вершина соответствует подстроке (w-1) -length, которая может быть либо префиксом, либо суффиксом некоторой строки в матрице. Одна вершина может соответствовать нескольким подстрокам. Подключите эти вершины к краям h. Каждому ребру соответствует строка матрицы. Он направлен от вершины, соответствующей этому префиксу строки, вершине, соответствующей этому суффиксу строки.

Чтобы определить, является ли какая-либо перестановка строк теплицевой матрицей, достаточно проверить, является ли построенный граф эйлеровым графом. Чтобы найти перестановку, достаточно найти Эйлеровский путь на этом графике.

Нам нужен эффективный способ связывания вершин и ребер. Прямой подход предполагает сравнение каждой пары подстроки строк. Это не очень интересно из-за сложности времени O (h 2 * w).

Здание Обобщенное дерево суффиксов (или массив суффикса) для строк матрицы нуждается только в времени O (h * w). И это дерево позволяет связывать вершины и ребра также в линейном времени: каждый внутренний node с глубиной w-1 представляет некоторую подстроку (w-1) -length (вершина); каждый лист, прикрепленный к этому node, представляет собой некоторый суффикс строки (входящий край); и каждый лист, прикрепленный к этому ребенку node, представляет собой некоторую строку, содержащую эту подстроку в качестве префикса (исходящий край).

Другой альтернативой является использование хэш-карты. С подстрокой (w-1) -length строки матрицы в качестве ключа и пары списков индексов строк (для строк, где эта подстрока является префиксом/суффикс) в качестве значения. Сравнивая с суффиксом tree/array подход, это позволяет упростить реализацию, требует меньше памяти (каждому ключу нужно только пространство для хэш-значения и указатель на начало подстроки), должен работать быстрее (в среднем), но имеет худшую худшую сложность: О (ч 2 * ш).

Ответ 2

Один простой подход, который будет работать для малых матриц:

Sort the rows of M
For each choice of start row
    For each choice of end row
         construct a Toeplitz matrix T from the given start and end row
         Sort the rows of T and compare to M
         If you find a match then T is a permutation of M that is Toeplitz

Это основано на том, что матрица Тёплица однозначно определена после того, как вы знаете начальную и конечную строки.

Однако этот подход не особенно эффективен.

Пример кода Python

M= [[0, 1, 1],
   [1, 1, 0],
   [1, 0, 1]]

n=len(M)
M2 = sorted(M)
for start in M2:
    for end in M2:
        v = end+start[1:]
        T = [v[s:s+n] for s in range(n-1,-1,-1)]
        if sorted(T)==M2:
            print 'Found Toeplitz representation'
            print T

печатает

Found Toeplitz representation
[[0, 1, 1], 
 [1, 0, 1], 
 [1, 1, 0]]
Found Toeplitz representation
[[1, 0, 1],
 [1, 1, 0],
 [0, 1, 1]]
Found Toeplitz representation
[[1, 1, 0], 
 [0, 1, 1], 
 [1, 0, 1]]

Ответ 3

Вы можете провести предварительную проверку для условия исключения:

  • Определите сумму столбцов всех столбцов матрицы.
  • Теперь в любой перестановке строк значения в столбцах должны оставаться в одном столбце.
  • Таким образом, разница между суммой любых двух соседних столбцов должна быть максимальной 1.

Кроме того, если я и я + 1 - два соседних столбца, то:

  • Если sum(i+1) = sum(i) + 1, то мы знаем, что самый нижний элемент в столбце я должен быть 0, а самый верхний элемент в столбце (i + 1) должен быть 1.

  • Если sum(i+1) = sum(i) - 1, то мы знаем, что самый нижний элемент в столбце я должен быть 1, а самый верхний элемент в столбце (i + 1) должен быть 0.

  • Если sum(i+1) = sum(i), то мы знаем, что самый нижний элемент в столбце я должен быть равен самому верхнему элементу в столбце (i + 1).

Вы также можете провести подобную проверку, суммируя строки и посмотреть, есть ли какая-либо перестановка, в которой разница между суммой любых двух соседних строк не более одной.

Конечно, вам все равно придется проводить комбинаторный поиск, но указанный выше фильтр может уменьшить сценарии поиска.

Это связано с тем, что теперь вам нужно искать пару (кандидатов сверху и снизу) строк, которые удовлетворяют вышеуказанным 3 условиям для каждой пары соседних столбцов.

Кроме того, эта оптимизация не будет очень полезна, если количество строк намного больше числа столбцов.