Определить все квадратные подматрицы заданной матрицы NxN в C++

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

Чтобы определить все возможные матрицы 2x2, мне нужно выполнить цикл 4 раза. Точно так же для матриц 3x3 мне нужно выполнить цикл 6 раз и так далее. Есть ли способ генерировать код на С++, чтобы код для циклов генерировался динамически? Я проверил несколько ответов, связанных с генерацией кода на C++, но в большинстве из них используется python. Я понятия не имею о питоне. Итак, можно ли написать код для генерации кода на C++?


person Vineel    schedule 15.06.2016    source источник
comment
Вы можете сгенерировать много кода, если используете шаблоны. Если вы опубликуете код, который вы написали бы вручную для подматриц 2x2 и подматриц 3x3, вы можете получить помощь в том, как обобщить это для подматриц MxM.   -  person R Sahu    schedule 15.06.2016
comment
Какой алгоритм вы используете для определения всех возможных подматриц 2x2 и почему вам нужно динамически генерировать код?   -  person Bob__    schedule 15.06.2016
comment
Вы знаете, если N станет больше, количество подматриц будет расти экспоненциально. Зачем вам нужны все они?   -  person polfosol ఠ_ఠ    schedule 15.06.2016
comment
@Bob__ Сначала я выбираю два столбца, а затем две строки. Для набора двух столбиков нужно 2 петли и для рядов 2 петли. Вот так у меня получается 4 петли. В основном четыре итератора из 4 циклов предназначены для 2 строк и 2 столбцов, которые образуют матрицу 2x2.   -  person Vineel    schedule 15.06.2016
comment
@polfosol Я хотел бы знать, являются ли какие-либо из них единственными. Пожалуйста, ответьте, если у вас есть лучший способ определить, является ли какая-либо из подматриц единственной. Спасибо.   -  person Vineel    schedule 15.06.2016
comment
@vineel Общая проблема намного сложнее, чем кажется. Мне нужно еще подумать, но, к сожалению, сейчас у меня недостаточно времени.   -  person polfosol ఠ_ఠ    schedule 16.06.2016


Ответы (1)


Если я понимаю, о чем вы говорите, вы имеете в виду, что вам требуется M циклов для выбора M строк и M циклов для M столбцов для подматрицы M x M, 1 ‹= M ‹= N

Для этого не нужно 2*м петель. Нет необходимости динамически генерировать код с постоянно растущим числом циклов!

По сути, вам нужно «объединить» все возможные комбинации i_{1}, i_{2},..., i_{M} и j_{1}, j_{2},..., j_{M}, такие что 1 ‹= i_{1} ‹ i_{2} ‹ ... ‹ i_{M} ‹= N (и аналогично для j)

Если у вас есть все возможные комбинации всех таких i_{1},..., i_{M}, вы, по сути, закончили.

Скажем, например, вы работаете с матрицей 10 x 10, и вам требуются подматрицы 4 x 4.

Предположим, вы изначально выбрали строки {1, 2, 3, 4} и столбцы {1, 2, 3, 4}. Затем выберите столбец {1, 2, 3, 5}. Далее {1, 2, 3, 6} и так далее до {1, 2, 3, 10}. Затем выберите {1, 2, 4, 5}, затем {1, 2, 4, 6} и так далее, пока не дойдете до {7, 8, 9, 10}. Это один из способов генерировать все комбинации ("10 выберите 4") в последовательности.

Давай, напиши функцию, которая генерирует эту последовательность, и все готово. Он может принимать на вход M, N, текущую комбинацию (как массив значений M) и возвращать следующую комбинацию.

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

Я выразил это немного свободно. Если что-то не ясно, я могу отредактировать, чтобы обновить свой ответ.


Редактировать:

Я буду предполагать, что индекс цикла начинается с 0 (способ С++!). Для дальнейшей разработки алгоритма, учитывая одну комбинацию в качестве входных данных, следующую комбинацию можно сгенерировать, рассматривая комбинацию как своего рода «счетчик» (за исключением того, что цифры не повторяются).

Отказ от ответственности: я не запускал и не тестировал приведенный ниже фрагмент кода. Но идея есть для вас, чтобы увидеть. Кроме того, я больше не использую C++. Потерпите меня за любые ошибки.

// Requires M <= N as input, (N as in N x N matrix)
void nextCombination( int *currentCombination, int M, int N ) {
    int *arr = currentCombination;
    for( int i = M - 1; i >= 0; i-- ) {
        if( arr[i] < N - M + i ) {
            arr[i]++;
            for( i = i + 1, i < M; i++ ) {
                arr[i] = arr[i - 1] + 1;
            }
            break;
        }
    }

}

// Write code for Initialization: arr = [0, 1, 2, 3]
nextCombination( arr, 4, 10 );
// arr = [0, 1, 2, 4]

// You can check if the last combination has been reached by checking if arr[0] == N - M + 1. Please incorporate that into the function if you wish.

Редактировать:

На самом деле я хочу проверить сингулярность всех возможных подматриц. Мой подход состоит в том, чтобы вычислить все подматрицы, а затем найти их определители. Однако после вычисления определителя матриц 2x2 я буду хранить их и использовать при вычислении определителей матриц 3x3. И так далее. Можете ли вы предложить мне лучший подход. У меня нет ограничений в пространстве и времени. - винель

Прямой подход с использованием того, что вы предлагаете, состоит в том, чтобы индексировать детерминанты на основе комбинации строк и столбцов, которая составляет подматрицу. Сначала сохраните определители для подматриц 1 x 1 в хэш-карте (в основном сами записи).

Таким образом, хэш-карта для случая 10 x 10 будет выглядеть следующим образом
{ "0-0" : arr_{0, 0}, "0-1" : arr_{0, 1}, . . . "1-0" : arr_{1, 0}, "1-1" : arr_{1, 1}, . . . "9-9" : arr_{9, 9} }

Когда M = 2, вы можете вычислить определитель, используя обычную формулу (определители для подматриц 1 x 1 были инициализированы), а затем добавить к хэш-карте. Хэш-строка для подматрицы 2 x 2 будет выглядеть примерно так: 1:3-2:8, где индексы строк в исходной матрице 10 x 10 равны 1,3, а индексы столбцов равны 2, 8. В общем случае для подматрицы m x m определитель может быть определено путем поиска всех необходимых (уже) вычисленных (m - 1) x (m - 1) определителей - это простой поиск хэш-карты. Снова добавьте определитель к хэш-карте после вычисления.

Конечно, вам может понадобиться немного изменить функцию nextCombination() - в настоящее время она предполагает, что индексы строк и столбцов идут от 0 до N - 1.

С другой стороны, поскольку все подматрицы должны обрабатываться, начиная с 1 x 1, вам не нужно что-то вроде функции nextCombination(). Учитывая матрицу 2 x 2, вам просто нужно выбрать еще одну строку и столбец, чтобы сформировать матрицу 3 x 3. Поэтому вам нужно выбрать один индекс строки (это не часть индексов строк, которые составляют подматрицу 2 x 2) и аналогично один индекс столбца. Но выполнение этого для каждой матрицы 2 x 2 приведет к созданию повторяющихся матриц 3 x 3 - вам нужно придумать какой-то способ устранить дубликаты. Один из способов избежать дублирования — выбирать только такие строки/столбцы, индекс которых больше, чем самый высокий индекс строки/столбца в подматрице.

Опять же, я свободно определил идею. Вы можете опираться на это.

person Prashanth Puranik    schedule 15.06.2016
comment
Просто добавим: поскольку существует 10C4 комбинаций для каждой строки и столбца, общее количество подматриц будет (10C4) ^ 2 - person Prashanth Puranik; 15.06.2016
comment
OT, в SO нет Mathjax, но вы можете использовать i ‹sub› 1 ‹/sub› для индексов... - person Bob__; 15.06.2016
comment
@PrashanthPuranik Но как сгенерировать эти комбинации 10C4 без использования циклов? Если вы считаете, что я не правильно понял, пожалуйста, уточните свой ответ. Спасибо - person Vineel; 15.06.2016
comment
Я хочу сказать, что вам не нужно использовать циклы 2*M для генерации комбинаций. Алгоритм, который я упомянул, является одним из способов создания комбинаций строк/столбцов в последовательности. - person Prashanth Puranik; 16.06.2016
comment
Я внес изменения, чтобы включить алгоритм для создания следующей комбинации (добавлен отказ от ответственности) - person Prashanth Puranik; 16.06.2016
comment
@PrashanthPuranik Большое спасибо, я написал код, он работает. Я подумаю над алгоритмом. На самом деле я хочу проверить сингулярность всех возможных подматриц. Мой подход состоит в том, чтобы вычислить все подматрицы, а затем найти их определители. Однако после вычисления определителя матриц 2x2 я буду хранить их и использовать при вычислении определителей матриц 3x3. И так далее. Можете ли вы предложить мне лучший подход. У меня нет ограничений в пространстве и времени. - person Vineel; 16.06.2016
comment
Эй, это работает как счетчик - что-то вроде заправочной станции/автозаправочной станции/заправочной машины для бензина. Цифры увеличиваются, начиная справа, и когда вы достигаете максимальной цифры в позиции (9 для используемой нами десятичной системы!), она увеличивает цифру влево и сбрасывает текущую рассматриваемую цифру до 0 (цифра минимального значения) - за исключением в в нашем случае мы не сбрасываем в ноль, мы сбрасываем на основе какой-то другой логики - это то, что делает внутренний цикл for, вы можете понять :) - это несколько сложно объяснить словами. - person Prashanth Puranik; 16.06.2016