Сортировка бинарной 2D матрицы? - PullRequest
6 голосов
/ 19 ноября 2009

Я ищу здесь несколько указателей, так как не знаю, с чего начать исследование.

У меня есть 2D матрица с 0 или 1 в каждой ячейке, например:

  1 2 3 4
A 0 1 1 0
B 1 1 1 0
C 0 1 0 0
D 1 1 0 0

И я бы хотел отсортировать его так, чтобы он был как можно более «верхним треугольным», например:

  4 3 1 2
B 0 1 1 1
A 0 1 0 1
D 0 0 1 1
C 0 0 0 1

Строки и столбцы должны оставаться неизменными, то есть элементы не могут быть перемещены по отдельности и могут быть заменены только «целыми».

Я понимаю, что, вероятно, будут патологические случаи, когда матрица имеет несколько возможных отсортированных результатов (т. Е. Одинаковой формы, но отличается идентичностью "исходных" строк / столбцов.)

Так, кто-нибудь может подсказать, где я мог бы найти некоторые отправные точки для этого? Существующая библиотека / алгоритм были бы хороши, но я позволю себе знать название проблемы, которую я пытаюсь решить!

Я сомневаюсь, что это проблема линейной алгебры как таковая, и, возможно, есть какая-то техника обработки изображений, которая применима.

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

Подробнее : Еще немного информации о том, что я пытаюсь сделать, может помочь уточнить. Каждый ряд представляет конкурента, каждый столбец представляет вызов. Каждый 1 или 0 представляет «успех» для участника в конкретной задаче.

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

Примечание к принятому ответу : Я принял моделируемый отжиг как "ответ" с оговоркой, что этот вопрос не имеет правильного ответа. Это кажется хорошим подходом, хотя на самом деле мне не удалось придумать функцию оценки, которая работает для моей проблемы.

Ответы [ 6 ]

6 голосов
/ 19 ноября 2009

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

(Однако это также не соответствует вашему желанию, чтобы вставки могли выполняться постепенно.)

Отборочные

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

  2. Разработать набор операций, которые разрешены в матрице. Ваше описание было немного двусмысленным, но если вы можете поменять строки, то одна операция будет SwapRows(a, b). Другой может быть SwapCols(a, b).

Петля отжига

Я не буду давать полное изложение здесь, но идея проста. Вы выполняете случайные преобразования в матрице, используя ваши операции. Вы измеряете, насколько «лучше» матрица после операции (используя функцию производительности до и после операции). Затем вы решаете, следует ли совершить это преобразование. Вы повторяете этот процесс много .

Решение о том, следует ли зафиксировать преобразование, является забавной частью: вам нужно решить, выполнять эту операцию или нет. К концу процесса отжига вы принимаете только те преобразования, которые улучшили оценку матрицы. Но раньше, в более хаотичное время, вы разрешаете трансформации, которые не улучшают счет. В начале алгоритм "горячий" и все идет. В конце концов алгоритм охлаждается и допускаются только хорошие преобразования. Если вы линейно охладите алгоритм, то выбор: принять ли преобразование:

public bool ShouldAccept(double cost, double temperature, Random random) {
    return Math.Exp(-cost / temperature) > random.NextDouble();
}

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

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

Алгоритм оценки

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

Как вы измеряете «идеальное решение» - треугольность? Вот наивный и простой бомбардир: для каждого очка вы знаете, должен ли он быть 1 или 0. Добавьте +1 к оценке, если матрица верна, -1, если она неверна. Вот некоторый код, поэтому я могу быть явным (не проверено! Пожалуйста, просмотрите!)

int Score(Matrix m) {
    var score = 0;
    for (var r = 0; r < m.NumRows; r++) {
        for (var c = 0; c < m.NumCols; c++) {
            var val = m.At(r, c);
            var shouldBe = (c >= r) ? 1 : 0;
            if (val == shouldBe) {
                score++;
            }
            else {
                score--;
            }
        }
    }
    return score;
} 

С помощью этого алгоритма оценки случайное поле с 1 и 0 даст оценку 0. «Противоположный» треугольник даст наиболее отрицательный результат, а правильное решение даст наиболее положительный результат. Разница между двумя счетами даст вам стоимость.

Если этот бомбардир не работает для вас, вам нужно будет «настроить» его, пока он не произведет нужные вам матрицы.

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

1 голос
/ 21 августа 2012

Ищите статью 1987 года Анны Любив "Вдвойне лексические упорядочения матриц".

Ниже приводится цитата. Порядок не идентичен тому, что вы ищете, но довольно близок. Если ничего другого, вы сможете получить оттуда довольно хорошую идею.

http://dl.acm.org/citation.cfm?id=33385

1 голос
/ 19 ноября 2009

Я придумал приведенный ниже алгоритм, и он, кажется, работает правильно.

Фаза 1: перемещение строк с наибольшим 1 с и столбцов с наибольшим 1 с правым.

  1. Первые строки. Сортируйте строки, считая их 1 с. Нам все равно если 2 строки имеют одинаковое количество 1 с.
  2. Теперь столбцы. Сортировка по считая их 1 с. Нам все равно если 2 кола имеют одинаковое количество 1 s.

Фаза 2: повтор фаза 1 , но с дополнительными критериями, так что мы удовлетворяем морфу треугольной матрицы.
Критерий для строк: если 2 строки имеют одинаковое количество 1 с, мы перемещаем вверх строку, начинающуюся с меньшего числа 0 с.

Критерий для столбцов: если 2 столбца имеют одинаковое число 1 с, мы перемещаем вправо столбец, у которого меньше 0 с внизу.


Пример:

Фаза 1

  1 2 3 4                     1 2 3 4                   4 1 3 2
A 0 1 1 0                   B 1 1 1 0                 B 0 1 1 1
B 1 1 1 0  - sort rows->    A 0 1 1 0  - sort cols->  A 0 0 1 1
C 0 1 0 0                   D 1 1 0 0                 D 0 1 0 1
D 1 1 0 0                   C 0 1 0 0                 C 0 0 0 1

Фаза 2

  4 1 3 2                     4 1 3 2
B 0 1 1 1                   B 0 1 1 1
A 0 0 1 1  - sort rows->    D 0 1 0 1  - sort cols-> "completed"
D 0 1 0 1                   A 0 0 1 1
C 0 0 0 1                   C 0 0 0 1

Редактировать: Оказывается, мой алгоритм не всегда дает правильные треугольные матрицы.
Например:

Фаза 1

   1 2 3 4                    1 2 3 4                
A  1 0 0 0                  B 0 1 1 1                
B  0 1 1 1 - sort rows->    C 0 0 1 1  - sort cols-> "completed"
C  0 0 1 1                  A 1 0 0 0                
D  0 0 0 1                  D 0 0 0 1                

Фаза 2

   1 2 3 4                    1 2 3 4                   2 1 3 4
B  0 1 1 1                  B 0 1 1 1                 B 1 0 1 1
C  0 0 1 1 - sort rows->    C 0 0 1 1  - sort cols->  C 0 0 1 1
A  1 0 0 0                  A 1 0 0 0                 A 0 1 0 0
D  0 0 0 1                  D 0 0 0 1                 D 0 0 0 1
                           (no change)

(*) Возможно, фаза 3 увеличит хорошие результаты. На этом этапе мы размещаем строки, которые начинаются с меньшего числа 0 s в верхней части.

0 голосов
/ 23 ноября 2009

Обрабатывать строки как двоичные числа с самым левым столбцом в качестве старшего значащего бита и сортировать их в порядке убывания сверху вниз

Рассматривайте столбцы как двоичные числа с самым нижним рядом как наиболее значимый бит и сортируйте их в порядке возрастания слева направо.

Повторяйте, пока не достигнете фиксированной точки. Доказательство того, что алгоритм заканчивается слева в качестве упражнения для читателя.

0 голосов
/ 19 ноября 2009

Базовый алгоритм:

  1. Определить суммы строк и сохранить ценности. Определить суммы столбцов и хранить значения.
  2. Сортировка сумм строк в порядке возрастания. Сортировать столбец суммы в порядке возрастания.

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

0 голосов
/ 19 ноября 2009

Вот отправная точка:

Конвертировать каждую строку из двоичных битов в число

Сортировка чисел в порядке убывания.

Затем преобразуйте каждую строку обратно в двоичный файл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...